package org.bouncycastle.pqc.crypto.test;

import java.security.SecureRandom;

import junit.framework.TestCase;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.pqc.crypto.ExhaustedPrivateKeyException;
import org.bouncycastle.pqc.crypto.lms.HSSPrivateKeyParameters;
import org.bouncycastle.pqc.crypto.lms.LMOtsParameters;
import org.bouncycastle.pqc.crypto.lms.LMSKeyGenerationParameters;
import org.bouncycastle.pqc.crypto.lms.LMSKeyPairGenerator;
import org.bouncycastle.pqc.crypto.lms.LMSParameters;
import org.bouncycastle.pqc.crypto.lms.LMSPrivateKeyParameters;
import org.bouncycastle.pqc.crypto.lms.LMSPublicKeyParameters;
import org.bouncycastle.pqc.crypto.lms.LMSSigner;
import org.bouncycastle.pqc.crypto.lms.LMSigParameters;
import org.bouncycastle.pqc.crypto.util.PrivateKeyFactory;
import org.bouncycastle.pqc.crypto.util.PrivateKeyInfoFactory;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.encoders.Hex;

public class LMSTest
    extends TestCase
{
    public void testKeyGenAndSign()
        throws Exception
    {
        byte[] msg = Strings.toByteArray("Hello, world!");
        AsymmetricCipherKeyPairGenerator kpGen = new LMSKeyPairGenerator();

        kpGen.init(new LMSKeyGenerationParameters(
            new LMSParameters(LMSigParameters.lms_sha256_n32_h5, LMOtsParameters.sha256_n32_w4), new SecureRandom()));

        AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();

        LMSSigner signer = new LMSSigner();

        signer.init(true, kp.getPrivate());

        byte[] sig = signer.generateSignature(msg);

        signer.init(false, kp.getPublic());

        assertTrue(signer.verifySignature(msg, sig));
    }

    public void testKeyGenAndSignSha256_192()
        throws Exception
    {
        byte[] msg = Strings.toByteArray("Hello, world!");
        AsymmetricCipherKeyPairGenerator kpGen = new LMSKeyPairGenerator();

        kpGen.init(new LMSKeyGenerationParameters(
            new LMSParameters(LMSigParameters.lms_sha256_n24_h5, LMOtsParameters.sha256_n24_w4), new SecureRandom()));

        AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();

        LMSSigner signer = new LMSSigner();

        signer.init(true, kp.getPrivate());

        byte[] sig = signer.generateSignature(msg);

        signer.init(false, kp.getPublic());

        assertTrue(signer.verifySignature(msg, sig));
    }
    
    public void testKeyGenAndSignShake256_192()
        throws Exception
    {
        byte[] msg = Strings.toByteArray("Hello, world!");
        AsymmetricCipherKeyPairGenerator kpGen = new LMSKeyPairGenerator();

        kpGen.init(new LMSKeyGenerationParameters(
            new LMSParameters(LMSigParameters.lms_shake256_n24_h5, LMOtsParameters.shake256_n24_w4), new SecureRandom()));

        AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();

        LMSSigner signer = new LMSSigner();

        signer.init(true, kp.getPrivate());

        byte[] sig = signer.generateSignature(msg);

        signer.init(false, kp.getPublic());

        assertTrue(signer.verifySignature(msg, sig));
    }

    public void testKeyGenAndSignTwoSigsWithShard()
        throws Exception
    {
        byte[] msg1 = Strings.toByteArray("Hello, world!");
        byte[] msg2 = Strings.toByteArray("Now is the time");

        AsymmetricCipherKeyPairGenerator kpGen = new LMSKeyPairGenerator();

        kpGen.init(new LMSKeyGenerationParameters(
            new LMSParameters(LMSigParameters.lms_sha256_n32_h5, LMOtsParameters.sha256_n32_w4), new SecureRandom()));

        AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();

        LMSPrivateKeyParameters privKey = ((LMSPrivateKeyParameters)kp.getPrivate()).extractKeyShard(2);

        assertEquals(2, ((LMSPrivateKeyParameters)kp.getPrivate()).getIndex());

        LMSSigner signer = new LMSSigner();

        assertEquals(2, privKey.getUsagesRemaining());
        assertEquals(2, privKey.getIndexLimit());
        assertEquals(0, privKey.getIndex());

        signer.init(true, privKey);

        byte[] sig1 = signer.generateSignature(msg1);

        assertEquals(1, privKey.getIndex());

        signer.init(false, kp.getPublic());

        assertTrue(signer.verifySignature(msg1, sig1));

        signer.init(true, privKey);

        byte[] sig = signer.generateSignature(msg2);

        assertEquals(2, privKey.getIndex());

        signer.init(false, kp.getPublic());

        assertTrue(signer.verifySignature(msg2, sig));

        try
        {
            sig = signer.generateSignature(msg2);
            fail("no exception");
        }
        catch (ExhaustedPrivateKeyException e)
        {
            assertEquals("ots private key exhausted", e.getMessage());
        }

        signer.init(true, ((LMSPrivateKeyParameters)kp.getPrivate()));

        sig = signer.generateSignature(msg1);

        assertEquals(3, ((LMSPrivateKeyParameters)kp.getPrivate()).getIndex());

        assertFalse(Arrays.areEqual(sig1, sig));

        signer.init(false, kp.getPublic());

        assertTrue(signer.verifySignature(msg1, sig1));

        PrivateKeyInfo pInfo = PrivateKeyInfoFactory.createPrivateKeyInfo(kp.getPrivate());
        AsymmetricKeyParameter pKey = PrivateKeyFactory.createKey(pInfo.getEncoded());

        signer.init(false, ((HSSPrivateKeyParameters)pKey).getPublicKey());

        assertTrue(signer.verifySignature(msg1, sig1));
    }

    public void test_shouldRecogniseInvalidSignature()
        throws Exception
    {
        byte[] lmsPub = Hex.decode(
            "0000001800000010D88330CA119BBFF43228CD435B63966089A997C6083CC2AF9BFE4A9789888694EC2A92883B36015A");
        byte[] msg = Hex.decode("900E8860388B34E30A103184F8EA198CC8B397AD5D7D99C554B966B3D18E938754B77F8252642A17A6F75CEA0945D4385BC37B75ED67C20F90DAC462A3DADB67FB3BC9CC23754F43298515208C2AA0181C098DACF58EC21D84A2F7A2A8539CBB17E915AA5EF042E9707104B08546B1887D6CB54096F25010E527BD655EBFB52D");
        byte[] sig = Hex.decode("00AFBA640000001030734BD0D2A048BAFE3FDDE5828D5D1431A6B02B9BC4F428266277D400CB1DD82E8939940D4E4835825088D6B5ED893B285E1136E39F06BD41DDA933847B6B0E2CDDDEFC7B2041BB75D10CD9904D6665A03C9BFA82989BEB903F0E8B8ECB2BC8C356CCB55225B6D0ED03EDD57B28ACC7911397FAE097F7B8BB888464FA56DC5D18483C5406A9FB51B361ACD45025304210A7031D18CC692F62797F0BB1682DC424DC309616D26C2FFF12DB9B7AC9BED9E35FC31D6113422D14EED59078AA29CE5E0C02F63D3CCBC870F1D5BA65C16DD42D2A373D51ED384307F9C412F7D6B4B7ED7A1C3EDD749BCCFDAEE66F1922249F9DF3EEB3452481B20DF8C63576680F27FE727AD7207389F9335844F8AEE3B8F31DB99D317174F04A133D4E011F352C74E1B3A5D2CA921D03A395B917FD486BC8C59E06C1BB1F49BF1556DCE070C3E94FD14877AC84A86A83C868F5E2307141972A7F7C6823C1A7ED9DEE07B10E0C9C6D65D004B3E841ADD1C3DE4CBBEBA9701B40DAD2D6016A88B68EF76F974B6942B4F13388A47131BC41F4BADAAABA37965EBE1566A921A7BDA4960F77638B5145AE6A8BCCBB96C0D9A433DB2AE60F85CD43963A12BD555786F887794C8734A3C329E85138958DCB5AF95C0E430220514525F65CCDB2DF360546CDE80525739DEEC5947F25A8F9F5FE7CB775A73112367D7C171EBDC9164568AF4F40399B7FA170A7F145A98E03955A3226E2946510E763B56AA619B46325E98B5E7CB5AC07E1ED42A010ECC807BDF4C6809908B8E7C03734B8A979A89A63FEC1F9C6F3878A73954E8C4A1C1914A2356D82A4F4804EEDE288A75BF755654F26AC4955428E9FE81289E0A55B2AF7BA235C98ACD89485EE04DCDC337228FF1B0C465C5FA7456FB1DCEB6D2DFF6C95431E6600000015EDED6089F9AA257DE3C3FD6E9AFB511E2A344A5DB043D5C6CE97D8648C4B125EAC8DD85036291DAF73F32CFAD7FEB07297DDFBECF0471EDC2908C3BE91A4DCB8CF532C9F37E5A4E704A1196405C71115FC622BD51F993D44D3116B0CA31D538E4249B54A67D13C8A02B5434C761B04CE43224D252079231EA031164C8BC3D51F5634FE881C6A0376FA5F0A9FFC5BD6F0118847CC793BCB57CC9C4D4602B0234CD03B8D3C259AF1B3A70C312070D3E8762BBECA5B3E951B3F29C51B6C1A75D7606B89653E9E0148C3FE095752FDC65D3AA2C854240ABE63440204C29BBF4C81D6D87D2FB522CCA245E03132DBA4DC49E193387C7E127C40A7F9B4995752DB1EB347DD5E1FE00203C78AC297E87F56C0F8C581ECBA774CC55BBD03EF335390F7E04CDA220220D1B4870379598583C057327053F7179D3802501E01162D5DB837B344E428443DCAE9B00FE01DF67627BAEBCD60D44A9B21EC0B6576E50DAB72CD0D55A7023391B393311B3B256A3BC42045208E118847F12633FB1890D78F0A8CD5614075A02046215D850112D111414906394FB2096E414AA90591857486945BF57D30706D2491C00796599E7DC1CB7504BAC7A7C7BA5CF0195AAE8162422DCE061C907DBD21A26BE844D6251AECA33DEC28F57C2A0C38D3D4E2894B5B7F9393AD52849D531E7EA95C6D19483FDA55DD9A9E3A4028BB6C7B90A7FD1B65B4EBCC12AFEEA0382E24CDD3261DCDC1E7A9A4227FE76C11EA73EDE79F8E332727767484123500EC3D82256843503DD771B0BE626D7BBDD2AE838A166032F8ACC635B4B9FEED9A31EFFCC87320D969FC0FE3890DBE40268922D12ABE");

        LMSPublicKeyParameters pup = LMSPublicKeyParameters.getInstance(lmsPub);
        LMSSigner lmsSigner = new LMSSigner();

        lmsSigner.init(false, pup);

        assertFalse(lmsSigner.verifySignature(msg, sig));
    }

    public void test_should_verify_sha256_n24_w1()
        throws Exception
    {
        byte[] lmsPub = Hex.decode(
            "0000000A00000005BB9C1B5FCF1286C41F7DCDE9FB53A539C7E3E5EEF5FAB878BD36C04EAB54DEF7CC258C32A842C4FD");
        byte[] msg = Hex.decode("1BCC459B62CDA60458092ABF9BA110DEDC38B6CD819FDA8AEB7ABF935919F60FD73D6F4108CD86243D317802EE46392E7FC50BF3D7A80D8A0D4E68E8F1E336D00C1905D4CF90A4E82B8D758E29E8D85462B17790E90328DD123ED1ACB5B2B2B3C0A2EAC79A9BDFF655F5F600851FC8DEFA1E9AA397F672F6E0A06FAE86F9DD22");
        byte[] sig = Hex.decode("00000001000000052EDE1C14648A2B009E21AE1BC181BDCA54818914475BB58F40C5E602EEB4BB6E33E4256BD64008876E9C8691209C372D5A7A770A1CB819A1758CDD6BEBA1402B58DAA45DFF0DE3F7C15789925D6E8E86577872F879721FC6F07937E88646E417E9320FA1BDED37DC6C5346160170F9D4A0E8E47EA5A2C3D025A5D53E8A7BD87D1827FD421701C775323AB4274679BBD038C438A05E1AB7B91875D4B5BDE3E3E4D26B60141AE8B6349E0380E63D7E6B3A6B2B5CD1BF54A8B89DA615324222009107A131D1AA7F84D1771916C68AE6D477365D2030C2DB69F51D0B4D14FE482A03D204E33DF679040FA2246D9528DEA205841CA6F327696E370AED4A96C965A8E7677BECE391847287D44F3DC6C3334779AF3F4941C3F43550A0D4638A050BB90F587AB06CEB7431F486251F61356C8E7FF318DB2027A825EA89B8547BB346F1A7E0013173DE85357A6232871D3AED6E503B4CB8272F7F0BA004CD9E918A660B7E8114FAF3CC7D9F4FE69F5435C0E6A5BFF5BB63C0BD575775764B73C21F0F2931F3EE9AE58D0B924530601D01E6C2A2AB21BA0312722EB94D5651337E9055DE1F1B8EA9CBC993E2BD202251F9F1B76054F0B495EC6C32725B663E95C82D5003CAA34EB69A7D2A4901766945195CBFFBE72B940B2A6BA12F56BC4AA62D5961DDB97B564B7855EF2BCD686D34FCF0C8DE3B0EC6CDD3A4FB21EC53AA7016BEF53F8F3915B8990129E2F67E51FEE3909B8083915022664F196A662ABBF3DF24C63C207CF53358A2CD5C7EEB297B71208F81A641316F251445C015DE363A2F8AC5AA4B5BEC50C6B1768668FE2B0B858820D27F99742CBF5675FFC6CC9E33A4A3795D8CAFF83726F31C780EB9971E75E46C55FEFD081C3FF6784F7D0C9566E4ED92EFB23E4B5A0514DC5D1104E8845C1F58D0B0A2A2F69E04E66119BA96F480E11831751AE7FE6369330A79FDF5006ACA4717496C023055F5366092ED9835F6F57BB4601654BCF4AFD8CAA305ABCEEE0CD154346F146F188177CB2B203D220C24CF5D1E77912A0F01D8F883055A18C3222A2CF4E34FEBF3660D12B97675D9A4B6382C85674DFE2B660A99C24C2227BA0B96CDFAEEBC8EFA0718E473A4BCBD70ECBE840FAADE55B18299AFA9118FC27F482B69417EFAADD0710CFBCF3CA12F400FDBA3E8BD377FACF38B01A5A07187BA93CA52AB0B49F510A2953C16C888A1F18C129988DD6F4637DB7CA561A9A03229BA2C4B0EC13D2590241BFDC68D8F5038089A35592799AEB37D99E81A374EC78668FBB1E38546671A017AF33022F531C3185BE1092D59D17FB56F4CF1489799F0480B6FF521967F652B46AF7E94FC64602AFF2B8F6A73882BD0452C4A1AC68B4BCBE0C3702768A5D602A24ACFEF51A0B053C1E66D4D1C64CFD8EA8FF76AFB35A152485FFF64EDF6FB18CBBDE7E88CF30A4F76B0C12B71D0F3A3BBABF8A32DE6A60F59E28FEAB4A3B874D7B746099286152B2CCA4B2C3F98ED665B9FA1243649A2B0F10DCF10C26521A7A8C875B234003B57E90243D74B677313C3F1BA7CCD4D0B42ED7EA79D50178F29CD432F423C101705E291535B02DC1BC9694236B4C628EE0D45BB0FE06E4E450D63D457D71C0BFC2FC70A66DA02DC437A75652AD8833A0D2D328F5C8993EF07EA64E2A17BF2F1792078C2D7031CBE17E53509B9CC9EC44CDB6C01211CC97001ECFEC24DC71C14609158A79BE8BBDF1DE0AFFE73C30DF6F5A5392ED60F02033C7CA03DE232D4B0C7F5190A47D07EFA1AEDD5ADE1B0B086BF8F540B9B2E29E3E670D4538053830864AE03813C0FD1B667CC91416A64220E5B8B5C43454E7AEDFD22E68987598F21D4FAB24953A3216A12FD55F73168EE98E0E7391A69A5FA6418520B0C78B816FE846B15743886C5B0B582B43F264147040A3D2646B0686D5280A9F20DB9E6B4B918CCDB760060F33F6E4F9A3F90ADDC9CAC3D9D77E0D0AB479FE710BED79D150A290B037BA0071592A896E90980444C66B0ADE9852657140226F4C5E97919CC9561AA72EDEAAAAA610B8767DF3A2DC3FE844E98B37D26C8277C9103278CD655BB8E9453ED8AD61A54359F80E51F0E65B09A0E515C3D001209B1592CA87C87DE853E7905765718755124CC04B7C9F972BE8F731FFA87F541423E767C33A7D52B7219CAF53DAC8EB5852FCC91B01315A6211E789ADFC5716C8D4EBBD95B39975EC7B88DD282109AC71D4676F2EA1F9743E619D58BCCDBF837BAB74C4AC846D4BF6C8AB77151B42FBABB887AFBA87F74EEBECECC8C45ECA8FE26EC9CFA3C89DFA62F8BA39087B81F76E929B8B5112E8457EA42C9516E2BF3466427EC0F7572774B11BD626CC12ADEBC0238A932B75CE9FF9900F332D1818E5C0451A1CE7A74EF063E8F371E2183ACDF0C38B1DB098320F6BBA960B80A6925C6BDE61EAD96BEA847F776266A9EE226858E02AD785DC4F12E5287B389BEAE8B4C77B77480D1A5F357BF62AA41EF06FD859B178D17CFC6DEE117FCC8645F2CB5D666A589570643D4C1B5D44DF1552E3FF401B26D70C6C26C400914DBC63157380B8211B6EE9A713B05FAF7AB70D16E2BFBEECA75BC28BA7EE82D4B646D863DA5B77FCF3BA7121123267B0031647724E4A5B9593D922D5590991DC90A19EA4D9E5A567BB3DE3959EF1BA47FC29A9A331E34A3C3D4BDA1936F98C1AC3B006BD1528BEC0A60CA472ADE66D2FBAF7727FDF72BE2D5E93120308C16DA6E508442A2B6C22CFE7A43A58AF3FAD55FBDC8BFCC26CAEF4CB3DF62BC9A63263CAD84CCD47B2299D471173184988249837B59A2D99B7A6B05A3656EE32F1AC52B975682F1EC6FB132433F75C6BB1E7CDC7679340AC991706CBBACE6D8137C18E83C2A74BA5B80D7D5530362C0BF2BDBF62B6FC71CD01AB2C0E512A7B53624C58FCE7F7ED7D27DE9C5585DD76BE3C9A09E943D1A3A6BA6A3CF01AE47CC29ED201CD19CAAD15149F39791520E6235B8F3442F614E2880DF4BC7FA89478EA1930FDC9CAE7042E3BFDE540BB3C7E7B263B759094EA52DA3710FA7850F031F47DF4DF8B2466D608049D142CCD492E6CEDAC0BBE15ABD20082DF14E7CBAE77B80EC1C7077EE2BF31214AAE833CFD392246F947F76C35FCF6598C35F37020C0C9BB8E7FF67F2259CADEFF5F468B5CAAFC810541D332FB132DC8900D6C1415B71E5D6E9BD9A2A91E7CE41FA20CCE431399F20224DE076A88829DF8BC857A4E0D5819DEE384B15AF08A6D66CEB3DDFF9108D66D75EB321CCC3D8909951451B34DFE78E721A7151696AF3227203EDDC88B44BE7E2C3AD01BED76CF209C01D5C1E218F995F1486F0B86CBD6826CF0F11D605FE8273BDBE2259F54083F7F937273BF00983F072DFE4064F9A47124CE53BEE19F287882F27FE309D2DE0AA89EFEA412843C0853D4C437A6DB8E2F54BA6D5BE0E93467375B1D03449E0FE865D81E890D237744CAECDEB97707E00C4E255486A739E4A0E89971ACCFF973951E0EFF6CD1DC0DA0E5DC7A6BF60798A6998EA57790D01AF63312C096D5141E5E8A72CB62FD6E451E054F58FB13B8848FA6C5D020D5F35D4D1A920248003A478417C8F28AA44E7C327147BA1EBF1A600689913008F118CBD5517D4D2F1A6EB238D9C6D9F9E27ECA0552192BAC389C79BE528D03769D8232C53933099F5711E2FD7DB50614201E8F06636BC2B2B3C6AF7FA731565578E57ED4DACE821F8B06E147EA5FA050F913F6D6EA242DA02F32D229DC10D79069662376FEF772359FE3AB538D095E2FAB48AE7A048F5ACA53FEFB9367ECEBAB12738FDA5C9C70ACC17328BD1EA2CCE1185F11C6308EDE61BA5B0901B2A78D57178333A6095E3A2FBAE9CFE4B4BA8036D1E551A21A9BFD1265A6F8F4ACD40FCF32D1AE7B626D553C51242A3223AF016E41D55D7D632E5DBE3CA4FC0DD4B608F8F532D6011945471481498D0B04CD9F7099BBF73798518D6AD8E4D326D5D1306ADD455033872FDC9F4B459D7440113654ED4E4AFD1CA292ACCC776CB98FB9C2767EF51221AB148C9D7F7D6D8499EA6863BA7AED43A4F0A9EDDD6490EC60FA2F86A3BF4848479E70ABD8E2DCD0B763662A775C5B5A1AB26BEAB6E2B9E827E76D2373093CDB428BEF2998D2AFBE147392A2372BDD8926267AA87CABB51C031D53DDBC2B90ECEDCF36CC6A3167D77C13304E6307464EF527B793B89D27D6E71D5D6BC85F270FB8D9546531A314DFBED1CB6F70740BE4BC9BCD9BCE0C1D119C8259858F2532F674E6F5E1151989BE61BEAEACC57D36317ADA9A79C45B4175638D57A45CA53CA475298B561C36BB727833322182BD1C149FED8957820120117CEE99D2C2392E8AEB13B4D6EF25D87CE7CB223CCCB7E89E61A970B81BE9353098219AB439E7EA8ED239D79E261F3F7B87A9F0EA7BB0DA82BF314C4D4CD553973E7411037AB50EDB330C132CBB69D5A9883DAFF081961D7C1D49B1EFC33982992967AFD90BD8A65C816281FD62779E5B9C82796D4251EB503ECF4B292168F72267655E0694285E28FB0D6282A8DBEEB807D252950AB85DC9ADD61CD2CD49CCAC2C74D1803B59DCE91AAC667E81D924D967A47796D53CBF46A192C5A8E91489B67F37E4554FDC0537B9323DC2CDF4EF3297CA8A2F7DC9FCA65D981C7F18E00CE9D35C18EFB8B70444CC6013E0F22F391C0202183A2DE02A59D356C1CF2E55D65EED1FBE6C719F66A92B2E425B320407D2668CDEF4CEEEB7679424A5C1404C88198F22370BA33090BD25F568F6FB9AC3A933A4FF68AC9BCCBA5EE7B0831D5648B126BA9190B284F2630128AA64247D805DDF7E882C2AF1342E49824C70035550E20B755EBFE5600B8FB1472306848A8D4D1E3B79A941AE0C8E9529F3716B855677C949DE3148908D15EE1DA69BEAB409427B5471EA2BD9308A4264D24D2A60AADA5CCEBB88D7F4EADF77189E29E19E3A2348B1D074FB22BA71E682F631EAFF35CC7E56C236E708C18C7C57CC6FEBEA18C486D625D2B4AD69C51A479F22CBF9540F3FB9CB3CBEA8702BC6845E9EBC0F35C630B87FDFF16694F3019E0BD1BD9886660FD91AD0F49C25C8DCD4099B5D8E4B24BD102AF7D65C6F51EDC8D262DF3629811EADFB4EA5FF27CE5CA7B6DC0DDADE55E5452FCFD5C3E33D19D3E66C4929C6FAFFA17753AD40C74E2986CB8C17AB45ADECF8BB7AFC9F7F240063A4D5D864340A79AEE28B333D9B26E28441157C96F533068FCD4649A2E3203691268ED8A67701D5CD48F01B1543A27BE04A57015F5B4A52FF16D3E0F33C9E138966383C4CA5B52A812F9515F39E5DBA852D4F9252F497014241A18277D9838641C7D3C387187ABDA9ABC631B314B94F362397BFDEE023028AE83C389B2606D10B45A27CB0122106FA4F6978BF751104CC87B2C51CDEF8A174D77F9134E66068F6EF406D9662542F8FD776E489375EAD90DAA6ECB9A643CB769A0AE13A38C20DFE7B00B4951F5E8F8FDBDCD3ADADAD6714A787E71277DA5BF11E8E40E0BADF926A03C2176951BA0E79CE5BD6D505801FBFC663B5F78117BC6D9BFB81FB5AED66A297B21619100689BF9B2C140FC04399BB9ADD387522667780CCD8FFDCEB0E0EAF40091363420E70700471732BA76B82CA5FF609BB2867EBB18E6731FB376E0ED0B1A16E04D710A3B73D9D9A994A9A48105E72016F61C0DCDA3A4BFD7AB8E4D49452040C526082D63C47D2A7B8B6B04A607143F7A4F6970DE903BCE024B380CCB388580DA345F6089B93853309A77135A2AA98BB269DA7C47513DE8E39CA249739F0F805E6C19268E2902FBEF02104FE10B3026251D13F469D1544A7428E248133E1B08713075620DB81D982740DD784A449FD5D5598CD15F5B4B0AF73D9182190EED53273B4AAB3E07455FB577CE5DBA27F63A349D86665DAC82D3349127E27854C125C717CFDD3326D92C62C362734FB0107AB1DCDC960052E1FC796F72AD793B3023F32AD38E58B65AD46D6C1387DC425D33DCA3DAF153E71CE60A126C13594B2B79592735DBA631323D28C15E46BEFD2A1406055F0881C188F4912F2952EE51852FD5F0665567F66B0AFA1865292CDDD239161F7221F43379D4CB650D3CB3095C547A4171C32A9067239BB1D77CFEA8DD915AF62468BAC13F62E90D15D5420666215951094E54F6A1AB51944F93939943663E927997EBF2FBFD3D4EFB04D2D616D7E99942281595282EBBA23181E1C55FACA1217D06B931088D0EC446B1DEB281BFB1365457B8F8E28F4C1F2C840AA76383EF8A92053866E48F2E64E8C3FFE6AD84A5633B97A8BD775CDBCDF8D23D2CEFAF401B7E6236471618D63BC2C2FA3E0EFB6884CCB5DE0A16A31FDE0EB47BF811AFB138D2107CD49783F5A9DA214247258828759E44E8AEF92A7AA26A95081B6741DE9C15A5DCE127197396AFB5C93B0458C0F106181636789F327207A49FB23D037F0A7188A7E63DA968007119D6F918671951F77E03D121A2F31B0AE38AFE2AB2F0EE993A2D2CF49C531E66BE4CCD86B28CE4DAF9D3E71307CA87AE56F60B93B286E7828657BB6265FADB82A1BE5772E7F5E89BA2866C16400A2E0EF744830D644F7F976118CCE238EBB0B5564F6AEB37A9051EB4EECDFD7E51266FD14B56B66DEF1182C3FBEFA0DD2DAF7209FCE80A5C28B7A842CC0D376636B165079D68A53E3380EEAAF19624B334A7E95FC317A0123C670F97DAF9F38BEB80250DF03BC462F3740A864604C2D29B749458AA5389625645B06D90BCF7139267261E7294527FA96DFEA0018AEF0E053361F6E0BC6AD99E25C54E375AD32ADD2A0C45659027D4EF052A65D857B6A055F16092DB8BD226BA199512459089E0340000000A4C5E553CA23432A03396418B3C2F073F1F172FA526BF63EC88FA128DA3218BE6EB95396C602275A47D45C569A85A358F26AC695649C5053445CD90C56C05392810806D86F7BDDB4E4D2ABE9932D083F18F2A50C17294B7F865EA8ED09F17DBD884EC26100EB3C2CD06E4598F054CC09E21979B9D80CE0599");

        LMSPublicKeyParameters pup = LMSPublicKeyParameters.getInstance(lmsPub);
        validateSig(pup, sig, msg);
    }

    public void test_should_verify_shake_n24_w1()
        throws Exception
    {
        byte[] lmsPub = Hex.decode(
            "000000180000000DE188C16F2640A361227C63532B1003E806038B1ADF081AFD9D4C2C5702BAE427DCA7FD40D8135830");
        byte[] msg = Hex.decode("37965CE6378A0EAC5FF4180AFE4D08A23047F9781540263FBC5488F2760D2247032827FB45D6688370BBF25FA1A9D401350EE3D63714045E91A2BDA00E7E685153BAB4D34E3DB1141E318C199FB7E27AF49771DF5F7501B7FB7639F7EB86B5FDD591178324C898A6ED434B39CCFFD5CB99A926C37C3EE36A3DD89BE7E49F5769");
        byte[] sig = Hex.decode("003A808F0000000D409AB9BD0993BAD6FDD74779682B06AF517E6236449EBD40C51496C6534AE146ED6528BEFB3028A50089A33411E7B916520E6FD07FC51317FD990F184426A38F97CF78BCFB3BA46A287FF9EA892E9308E745F01BD4494854D0E9243A6EE139BF39E42CAC8EB568D3285ABCDDF6FB18E071B6A383455B8C2DEE94E88A5ED961274BD98CC4D293B869320FF22BCA1B69ACE337B7A1A1EC9179131023F8BCAC112DEB3B146D4409A99674D3C3F7D52B9FFD59A459F778F4E0E3AB91B5BE5289EDD47A7CEEA0A7B368F3637BAD33741AB3FD60E2B4842415ACCBF3B9A516CDC870DAA840C35D71DC3D3C6F5FCEE2FFEB6BFD2EABB34B01263E3C963867BBDBB8726B7204B1C78D3A4137CBEA598DB8277AF03EAFEC7D1342A874E4311430D796AC7EDC6608C5F91ED17E6B7087FAED38B940AC1E456749AFD4A6EC17F22BBFEC18473E1ACDD3D55CD0480941009C5CEBE49CA7671DCF0544AE6FEF13DCEE911C6D525E2CF6CFD0AA6CF20754328FD75FE271A79F10999715613F7BFA3E07BE783C61B65DE252D56B98455366410545710747623A26F7AF365F00DCE90948ABE79C98C58226378CFEA7B5FE479B4978201C3C172478E90EAB0B5D1F3B08B515FD08F7D30B3E08084174ECE5DAFBE6382E5B157D171E26408276DE527D088505FCD02E24E86745AD9CB97A09D799DADA00E9DE7E92B7333AF5A84A3FE7F935307EBAF6E7281D2E67F886368972D8EEE2BC518650C0660634E01D440FDE0BAAD232F2997AAF887647A557A5E6D91583EF9B061F36002F36724EE08939148C33C5DF83F9972C3F511D522740D0282762DC08D2F6A9CC3D5CEB8EA9A2DF8F9C2D8D675986E4396FD46F692BA3DE864969C63596BE105500FCC27EC15D33365ADFA5BACAFD6CF9C88ECD55947DB233D74A7CA711E4AB93BB48CA326B0944DA3BD4EB70DA3770C3BA8A5BC3BA96263E16394877EFAC613FB9AB5644F9744080548732804028A89F762EC4613545DE4AEE7306511ECBCDB02A35B771729953DD00250F4656ADC0EF1015C5FAC92D770158A5537BA54EA8205EDED7D9D703DC66CF5146AAE9B8259640B24B75C3FF1DB2B7474770C608C8B7248E8707967C1F5020AD74AF18BCD0BBE3824258F6ED47865DF2732572E137C87320366F251A13C8310241B216567B1D85D4FA76999AF64CBA131BEEB54F5DD56CE6F2477AE76A1F9755B57FD6A376F3E3BAD965F877C656A4BD7F071FE867F5C1DCAAC69FCD2A1C362B7CB9304A315C800F7E5F012E438CE2DB8D6C9613E2D13CCF2D703E659491A08B21A9C472F45931A0F3F2643C5E7EB4B8F0983AD44BBA5B6D7FA6A03ED4D0AE492F749329AB8688260258A260946014EB983E4AC62588707617BAC78E1E87CDB9204C1E86BB6715BF28F323DE120B6F684C827EFFBBCE7ACDC97ABC6B59BC87AB4A8F23CE5ABAA1B783B53EE8C1BA700A6FE847BC890A118FFA314E9F7DC905283BB02A84172D92CD2DA566B9A095DFBBBEA10CAEC6A989861536AF1804F5C30E9BD0F1AB4E8B5166A2A1348F58C5968FF9EB23519271941FF5D62FF83079CBA0BAC2C6C4A9B141CAD2838CB6FCD04644813FB7FD12E7D9E9B719DB33DA9DCE4A9178CAA8472805D199AAB655DC9B9D7F0BB47DF07A10850D42E0C8555144E6F02EC87FCABFB896BD144770FD98E426972B5FDD37C0A44F453AAFDA66605E8F78FB79AAE1A8923DDEA6EE979DB6576A9B962B92C0C1FCC8D1B2C774CDC50CFE6AC19BB4D058C533F4BFF795E0314385B58631A60D3F12F34543439D364A5DF5A8AB153DBC60A587D85F3B805885591232F31A2B972CCF5658A9993047F64E4B259EBC0D525DB23FAE95F0DF7296F1B35ED479CB124A18808133C48387CF79FA63408B0367DFF0522B161D2588DB5CEE667F435109DBF14CA9FD4A408B4EA0995EA1CEBDFAC320680B23D4EB50DF75F3A4263A8ABD88E5AD3A62DF7ACC6E2CFEB583A4DA5F919BE8FCD85D16D36791784B50EED2F072E23CB62741AF1680B62BF880C18F1231DD91A55D7ACB61FD6A34348F4311394B39C26E19154EC04F01A622C66CC528069BEA5E5D807342FCB31E2DE474D60E11EAF0B9E24F8F06DF72DC68EEFCAE17FA9A3704FEA8196675E2E0FF287DB1E025877B08005B7A0B1E96BFDD54C5F90C5803E3E552151244C03CCEFDC43689740E24981109898F5CDE4C16E4B29D074B73ACBFC4B288F7512F5580B04AAE0385AF1C2AF1FF4BAF4D8D8410F8DC2D0506755DD5C5BC0F7CC21DEFADA8AE32A59B790AAA2826681C7DD30AE0C723C3906E52720C2C61C7AAF162A833FF45A6710BE122019391E2DB6C3AF5985B2F905808A0ACB7EAC5F4C5D462D2E67D0596B15C58CE2228187DB68C06E2C56F2228CD8B9B9DF74C7D4FDA7B99499E49495FCDD275C4D5A48C4AAAA54C4D6A91A1DA40601933F97A7C843BF59F5F773F656362709F564815516D8A97AB17BA92A7C8300A572D8F8A71463EC446FB00A8D8459A030495D2C7F83FB48CD665CC750318BC6F1F79C9A8B5F515B0F7C6F9DE926824E6DBBE96F175B6FF0369DD0FD5EFC91A256A88D5D3E825065EAFFA98ED51470BE4DBFDABFFFA7351C8D779933C362FF41E3CF387AFF42841B208B1572AF015A08A3D7AE69D476660AB6E49247DB1A5FCB9E09F0804A3D72F1178F443BA64F8764BC4AF4746F815817623D91AF3403203AF89A5A8F60F8063AA481712EEC3E9E4BD1025725E068272C4742AB874D5AB2434A49450F9BC4BA581D582FDFF785AE4E663EFA3C9DC4AA63FF22CB96875C43FC9E19B33ECAA1AA6B6AB670EDDB843D7D218F7A3A26F10618AF43E246C3649034733F5EE86DB8BB2DA5BDF0B61B6BED4A8F774A07F62057758899537BCD46656231C2F470A9D382362CCB8ED747C25F1473C74A661A346202449F5B55EB65A68FCBE250F187BFA2B599AE7677DD8F27DF7369257F90435099D3D0E663626CBB9848CEF2115844A930DBDA36876A36C8469139EB25C660251E7E4B370EFC52CD046B01B8901C359A492F91D3B14388200F3470934E851887D49A9021A3129E9B7A0D83DF5E24B98906487E32004BB57FA4DE6A3FBCB2AC67D2428711ED5DB076396DECA297137FF2D33A61E8596248A0268F5776AF906E7F0744B684707F2C0E54B5B3FE59404FC999BE10CF5802533352584CACE95AA5B97AD04BD9685B43B2AB01663E181618010DDDA4C0EF5B10F4D50E96559EBDB6694BEEF2F299BA092C55470FF744F7AFE524E04447918B2600BFC68657CA79D3E453E85FA68E61F72B72A8123814ED0BA121205F13586DE25B66C3B824C6561DAD2F1145FE4D735EE76EA177D1F44242AE1D62D9B4845F45B44532F3CAFBEDD8F404BFA04736E8CB8F6A4002A7985BEC7360CBD2416416321C258CCBC70CF63ECE7766C9F6A1054588DD9DC74C5AEFE2821E97D72F4E232E35BB8A9DCBCF693976C3405D8BF95DE16AB807B0AB74A9CDB765F550FBFBFE1FCACC9DDB01A673BDED3A45491B4E525D6FF036E1FB8B3281F06FD0ED9932AF00B7353580B80CFC704DC242A9BB936302ED3DE804577E204E8FEE73932C291193BE50292B52916B7B68294B1CCB36C04AE7BEB29433AC458F526D9BAF304B136682EB5B6890F76D269A19C4D6D4B0073DE9055F48F3C4C60C97C4283DEBE41EEBF77CFD60AF50FA47D342EC8F529256DC66B38D3D03975C0B0A721F8D013A2721256D17EA524E17709B188B9453A8EAFBA9E3BDD6DE828BBA69F9BA4DC773C1715EDF9AB917CB22FEC219F35816BD9F2506882E4FF68FA6088FFA97AC402FFC07547283C4397C176CEDF72745064713CA1F3E71936D1E03A7BFC1F5E2F29F105337EACAB2E137BA86482517D04E3585C961AD0F2349E44BEB99CF8281FD6BB550A13CD691C47A11B0FAF99E187835BC603B67FC8CC1D87CD4DB11A4248A3730AD1DD3FF801BCB211F484DE41B1DD080169CC022FE7B793AF4C73952860B0866DA41A1A76B1BD6C7EC0E8FCE01129026194F74CAAEE3621578E45CE3A318F08CD2AB3A51269707875A0D23DF959860144E63578568D94F2821981EECBD4D40E3605F968B491D522A6A5E52969D7E020C8D7103FE7B001BBA75658A32DB147AF4B7C4BFAE5134640539BEA2CBD6B5F0C0FB3393CEDC3BAF5A3249810E47702CA6FEA5A124E933A4F6689FA8FA4C5E0AFCB87BBAC3AA09E55656CB922924A62A976C339EF163BF59D628118312A7B8F166EF92C6390134A5763A9EF62233BFAADF35E161C93163C0B65F9B09F56F6F9C3A650EBDAB88DE5B5DDE673605D71A5CCD0DC70FC77E575E0B9234834351FEAD0DC5D39B3E02689E0DBA7A37594CABD585587985A7B3077E61ABB026570D77DD1512E44A68113E86A569B5BC4CF68997B8E2ED2FACE7AA787CE10CD16CBDD5DD8DC85014B3583DBB3F0DC0A927579A9BE5F0937A1D92CCE62858DAF027F7CC88AE3430C9C0B3ACE11FC0CBB0E3B58FD6C69A6E03A5D79A3EE6ED649EF28A4FFF7EBF0A04C26E30E911DE0F42935D00181DB8AFB7C066E0B739A20AEF725816728F144FA4AE04179905CBD6B69443DE46D0D2BFB556685C11BC1D14D782592705CE89D26725D29D33643813F7A8FFC3237D2633D0C5BA210C5099EBD4B0DEA523FFFBE43A2F76E82130B8E0972B9F3419D6B4CFBE627AA547D4C811178638E104C7A4F17577A6BB0ED7B44CE7191BDBDAB14FA86DBCF82238DBA89A3DFC309F4A6FF6088FDF55BA4F24D7F78B5CAA625C2EE0B820148FDEE9D224A6A6483952281B1A27B7A7B0D7CF1DACF9EA607C35F4F4E5DF12C3531BB4FCF03D69EF7F26415C5AF7D4D8A3B5D5A58E68621C97789BB91E522ECA4499FFA6FFCAE2CE89A339CB290957386BBAA96479CD1FF4C1F9B81267B0DA71E8320CA31E56648DC369093C259E1B8A09A0F9A154CC3FC69CCD4B6C4BDF661F00A10BF6F49216A69AEA2ABCCA9891DDA801C3C93AF35000C51375A417BBD071D5C2C1C999D428126EC0D3590B7613AE2E683BAB3E68C176488424964027DBE633AB33F175827E7AEBF6A85C8A24DE63E6DA473829FE05C32C3BAC64FFB32EF5B5DFF18FC2B69AA8E78D6241A62E63DF19DE90523E01BDBD64D85E349E8C002B3C115067F70AE6ECF56A8B74CAC450B7476B236FF50904A3B3FFB0F021722F6FF13603B153D4236476A921784D88FFB3E26436E10BE441BF9FA6443203C67356903D01281051547776484FA38C68DD30A30466427B4C74A30E8C315D9454B7A9DAD7FCEFAD4B266A8A0F400D78B6A247CD80A4E9745A9B03E258AF019BD1ACC46BC322C5CE74F3861BF49A2A44F74EF7A676109378ACBFBC0AB0128F358EC1CADB9E22408DA5A05EA61B048BCFDDF6DAE2D20BD67B6F0350B6F40F3DF8F2A7842102FA096EB6C04B773CDDE83F2B21255E2A7A6D8D75B69541AAB744CC2D5E76D947DBE83151826455FCC185E5658A98C66CFDDB446934B53681BA51C0B4C1DB19D4A19602DB53E591D589187076E674F915E680580EAE077D3B2CF5F9343654A02EA1967201664C0E0C0298A3624196C8151E5706926EEFC79DF82FAF4A47E67449F0C9ECB91866F2CFF0BA8423787EAA415A69F2A2BDACA67BF05666D08A2058AA0A6012035ABB9C46CCF1B8AE95476B25FAC406270AD1C2DC48F762676D37B9543236C7B382C761FF12B7E5B738F8B266444AE1C718C09CF598482AB0DBAB8107ABA6FC465938C9CB1F305A0FC4EE7E3991D674C0F5E0C99E335CE6F1F2AD45FD617FED27E6F7090CDF228168DDD94CA396B47F10DB14A32FCF45A7AE7EE3B480E9FED7555DF608F5A2F9E89252C411D186BB5A6C30E47C6896138A6F1197795BA793C161029FBC6926030910E9D8D64C8482C282ABFFE81592CD13CD65C569A1E23E68C983C462A9950E15362BFA4AAAF78E86CC27171CE12DD7E018019A565E70611FE2288243AFF78FD27A08555F698AA1D809BE529A9537EE737C7903286A1AD5898A25E26E259095BA572B007066E1356921B023F8A17E288AB16D902F9F550599C6060A02FF09D05A70DDF74A5FB44ADD74780C233C978127DE646E00702F2F6C70816C1D281ABACB19F88FE5066A7B58A9B675FBE224A4AA6BEB692CCD62065A7368169E3C022F1383DAB6075690633B15DCF6E4BE6912F63E3EE58A860C2E139199101175ECE852F3AD5B91F56A417CC04B3F20E1DF1FAFF4CACD88153A9A9A84EA07415B3824FC8C5DAD91D2A9D373DAC5B1EA968297DE3889AD3E45EDF401201C04B3FFFE64C866C0B995A92C0247EAF49DF7C358730801E1158132EA5876D049B3185326BDFDD796ABA930F64716D21308AAC87AF5FEEAED35D1BC5EDAB2F079600ACD31F6786729CB36B545AA45A5F91EA6E14CDA7697129D0F6F6AE1A31D5D72E934273C965D0FCF5A27F68B3D29A2A46047B42708D999905D0CDC8DB052B362CA39F91D23257C1DC7B65C7D341689A8C8E1C5DD49C21776FFF0BDFDE54B8B87EEECE9062739E216D28EB86112F2F26F892BF64599E9F8B708FF9759C8B516EFA52D306C993D907E230CAA5365200A6504BF5A804636AAB43D74488E627ECB4AFFDC6B9270970C0FD556F1DE2B5E4154C539AF1064206D030ADE2B6E95D7C46AF08C6FAC6545FC10425AAA37B18540C05072FC7A1797466D5B38F7291DD21FD3811F92C550EA3F53A94ACF23A8B7543244C3065D216732A0E6A160784DD96A3D74DCD4B762FF06BC5E2D2892366345593B8FCD8DDE7F4AFC731AF8A3B77CE5EE98BBCB8001DFCA8B5CC282B0ECAF9E2682397CCE86E9865DA379236643C128E000000187D14B68025915B5F25949A569969578748E2058F65678698DE19D5D2707A3FBB54FA854935F833555CB69396C4A11E9880B7F991498D3077099632D19AD407F2FF1ADDFF5885D4F0FD3EFA9F5869BD0793B96DFA730C6F0EA1BD63E05FAFB084BEB80F549740EA4A9032E534DCCF469BFCDAFE5D58C1B41832102BBC0C5BE6945AB3662C239CA66AB4FFD8A679AE2E9C67749CE6E578D969CFB3405F7E71569797D759FCA5C1D3F8C8F17787D70DBF05F72734822A393DD3C4B123DF4BF9E984B420E35EACF645DE1D401CC5E5D6E32C9D15DAD80CBD493E74E7B75094983D077DD4046E530BC181D958CDE3BD77E2F71C1868DF461A048F603FD6ADF4C802250DD1AF6EE962A4B6FA8CD347FE9B662CB70AAC271E77356A0465CE6A2FDE7658FECCD1C582E4E733F98F12FF0DBF560070032E73B4BB14B106AB6D4E4F2C02D074368194468BB788975F77C806004ED8D6D5AF2A9A27CA8EB774037A9B505E25EF66AB692A27E2918427466646888A606DD71B6786FF109B0C3FEF6667B67A7C6034FEC2371F59EFE4231406A5CA61851DCF92FE76004BC838124273D253CCCAE3C077C3204490B20200CC283B5425C8C138313B4331638CC48E330C052C2902147A3F82CEA7C7344455234EF48791ACCF50965B6ECFE24AFE070004F1A9FE58FBE691FC8DD81AFB8ABD89272E033E590DD14C1B59BB38BFD3E6D9EADD250A944F8F2D68AC48EF0E59E6FA56C44F88F5E00DE8ACB300EB15DE2B3EDEBCDD731C934D64A4B321F3225BEB8010B5027DB3FF655E63ACB6B51C3B242B58AFEA6E379199A356BD83A28EFFAA8C9BBE3AB9519D409923525E34F0");

        LMSPublicKeyParameters pup = LMSPublicKeyParameters.getInstance(lmsPub);
        validateSig(pup, sig, msg);
    }

    public void test_should_verify_shake_n24_w2()
        throws Exception
    {
        byte[] lmsPub = Hex.decode(
            "000000170000000E5AB18087CB8CBE2C7884853AC5FB8E6E59EAA74E7DCD418FC0B4545BF12FC894B163C438C7B993D2");
        byte[] msg = Hex.decode("E95E2F0D429AC1A228DFE1F4D11675562A9DE1AA22AEC7E769F8609E2467083BC9382017FBAD3AFF52B1B91F7DEC31B6099F6F3F5A85060A762BBA7C991353E1FF5FE003CC7FF699DC3C3028B83E122475FAB27849089BAA3BED97F147163B82D9725E8F10A7B0BC17B947F52F41F70D1D0193D5952D535DEFF0AB7D3B0E5224");
        byte[] sig = Hex.decode("000459150000000E562823BD69497DC096C8DCF8DF74BAB93F3B4F7EDBAC174EA411A2279FA65295D82F397A0F84D830A9F8FAB22C3CBF52294452432A4769355B9188B38EB2C85FD315FC1208A05F06B5B8FFD7C10E6EBE103C5A1F18FEF97FAADF7400D71C2A2375ABAE2755A8895A159B9DD0CE15764D9F4A4EFE2E7BA471AC99793EE5F66C79743783015B51A72CEF3AD4F3EF34293C80863AC4526B97F22E21B2E11C5D24CDC04A8CA61BAFF3AC14CD12D3B040C8995A49B16A1C64CBB1AF22937688E776F0E0FF5B936E912615AD36F55ED573889C7C05634A923167FA5218738B6359F6016D3FE80A1F8A32426CD9D6C4871C6BFAA7650F1C7D139BF1AA2B5BD2B9211723D1592845D760A8E2448892B800273A2438854624707C60EB36AF2235B1E1C0911B05BDA5BB8C16E846910EAC51BAE0478A594DCDC335D939C1F1788EBFC99BBF9E903CDE01ABAB1E9E28047E380851012B1FF596A544A98574A72494DB6D7771017AC5127724AB596DAFC30B4643D590184FCCA3C118CC96D606C962C9807A16EF208D5849FC9287C4A7801803810D3DF028F17BA7BC6C09630E841FDB9B51DDDF909AF09BBF8B4F0120F962F6AB35F7B462E6C9E0C560E6FF530C417BC4E0E0B70BF1FB2F16E6903D9B15F940655E964078AA5F3406E70A20FFF375D8D0B0EB8218D265C9FBF185CB0C815BD50DD99A32992CF1D69660C690A4CB7EF4E27639B5E84061E7A37658570E06594CF45914B1D6FB36C1F6074326BE75E3110DB8787FD227902B93E56ED313FD08E43D6E5E8DC0236CABE0A8EED16CFF6228213DBB5875F6C129AF747A0843860690CF2C5F3FC090F0BACD70B918B40D90EF30D83828B5325EB930B0B755CFDEB227EB455B9AE2302C76B02334B419DB5812328D354A5DFD529CE6F062AA95179A226B06B041516BF9E3639BF8A1856C2E5174DEC88F5363BE1427645435C5D508EEA10B239F5988A0CB9672CF5B30961C626A498C170549D3BBB409DE88F9C5D8018DE2CDF938812F4DF5FAF91EC438CB770B76F8373A230E731A6A331F9376331EB3B6F105A1550FC1B8F69E4DC1C8BB11B740B5FA9070DD2640F5AF80852A8FBEC12825A0EEAB93E0E57EAE511B141FEEE4B11ECF0E9CAC764E08372291D73C99B7EAAC4327D9DF85D5336E6DC1BE662F7C7E07D37A479D963028E10F2D7F98516CBB0A017D3BFB95CE9558C65AE2623AEBBCAD409590289E53990C8029BB78FA1F03A480B74AF4C2F782A538999CB21DCF8DAD41BADECC2451D40BCE0B2C7BC32C38FDC119E055853C00E58BC50E0155AAC80FE6AD4391E94497417CE29FAFAC3B9C7EFF053CCF7D95641863D6F689F16B306C44E2492EA9DD8907E7ECB6FA0ECDE555B3AD1D5DF94526BAD2D57D9C639B2A482054A0598A4385F2D586EAB8D89E6CACB2214D1B5CA6806F7B3E0428E9129319A3F92BD4481AAEE820C41F79090775EDDBF862DE5C170F9C582D2CBA5FBA02373853A157094E1897FD476096E7522BA9D806D4A5C6B27729ECF38AAFD5EC6424E12DA2950F294BB9174880A843635F37773209F54E6BE92DF682D4F78A2D05BEBC6DC27E305BD31D94E75138856DAEB5B62F32FD70EAF3A2B2760EA2A43A8182651AFDE85BED1440ED8A9D26197319C3CA76798CF0497A76AAED4E98062AF8439D3B4EB298C4660DE1821530AEB73BBCF4D44F4550BFE87A5A17DA48DF7977EAE61D8480EA368C4A971CD05A260A2F596E9651782531531BD98DAD3C85F71EC58AB321C4CA1E6A26DC64466A080CEFBC108E0AF434FFFD65D51209ADB356976485523E59907245E79D21DFE74084C73DD5290F18527B5905B202963992758ACE41ADBF8F0988C4D185ABADFC98B25A5B1DB614B5A88E2A27B75CEF4416962FC366DA1557A7D6C5E2654D5300020FEB409D2CA6E53C3D5AB6F09015C60FD7B8C6E58692FDD3A6B05616FC485FF12410C49BF031F3BCC517F0D2F21DF4A86C000C0313FA3180D502F0A61B780C782D59D3C6B6458F6D86D7C18320D3543EF4533EDCEE82628EB411481D82166CDDEB9E65EEF053C327AA73C13763F889E80299D9F925CD7D4964FAFAAA796E811C5794277E33199191EE50D0E6E1C5AC27E746D6C32E7EDBE3ED772009D2F317424A799325984B44D019BA87139F06C91B678D9B58B3EA8B0235CAD7197D304B44A733D93CDE76D64595729C84D730B48368148999003873E40338752C460B4E7DCE2E1D04B7C8BFDC1BDDAC8D03C540A1192BC9011A08AD5BDD52E856D8AE2492F7644A5F212BB35607AC7B5E625074FF28D72E9DA179551A04A01506DABBADB14C2496CC6C0CEBFDDBCC39F3B5FC56C3778594F2DB804CFDA033F07E1DD9CB906ADE6D9FA215324AE9023CCF41C4BB06A4B9D09F3EECD45E9CC20FEB77DECB91B8D21E5E8E3001DB88187B3D451F915115A38F31317C1839730E4441ED309E5D51580A8EBB72672BC283B2D908A80A50E7CC2E4CBBE78687A0E83DFCF835EA441253F0C843EB01C953AB22E4AA8988C27D4207DBB1FEDCAD719C6FF839CFE15BD9D05CA61C3C0674F7089ADA5B85FD28184F24F09AC02F8A5B7B919F341B27B8F8143C4CA0E62BDA8678AD4731DB7A44B686E9C3CDFE64743FB88F0EFD21BB8E184B8F322ECDAA30D83471D785FEBF8B321BD47470A1010C175400B208E31ADB354DE2461CF23320E6F8B4AEEB9C35827085F2CE4D983B13D57C5268E29DA6D1155B7FFEC621CC0320ED1E41B81DC712B94C6AC0CB21E51A0B356DC2C9647052573D114203FEB57E48DB1508A3D530EE8E9D3D393E71CA72BBEE3934E5539E63DA7B51E31CD2A8469E06ED13C77FC05EC212A3B37093C9A8C2D66C952A347573870FBAD8865D9660A47A3B482D4930AE245EDB5F1D373DC293E1BD9EED01C79F9B090EB0131CA236A93C3989DAC5B30DBA1F0AB26DA805839C789BB74392485FC9B46DAE7DE98FA082E0A436FCC9CB2CD481FC625DFB6A2709455C693D5292E4E5C46CA9835E9D16F1E5D167968792BD89FFB42036E2611CF183380CC2015E85864FCD1340692C431ED54C6A54AC6DDAAAD79BBAB1DB0274EB852F646F3628C2AA880BF6082111607C38B6E35AF633A802BE7221FE7BF5F9F2A3447D229994613E548D80ECE807F504BB491851E866E7D910F32873DEC85D6F5099359657967E32AC70C57ABA8F9A7E45B9D80E12E7895764EE2ABBE081A62214A637680AEF17593E2D7AB057217A1941267E73F8FDA9B3D5DD9D2D6F874041DE41460F44F84CFA264EEBB939E1FB87ECB1C4E0F8671448956A76626AAA9DDF76E5CFC2CC83DFECD874AEE2F9D42E178C112E93C9468F5FAB27D7E1E0A364A215E25BCB230B9EEB844B80C62C2CDF9145379AA0F76D07155D1A2214E2D43368B0256325A266A98632ADE9F897B52294B43B5AAFD087C31772CE0E55FA32C7FD467A8110281803E81A4E0000001713C9D996AC9EC1518D4ACB08C00395221795B6024553C53AE08F21CA02C91E5D00D7FC1EC7FE6B441DB6F3AF4E1D54D9ED280EECD3C8FF4E3216DC1E59EC850502AB1C3F48B86B1599C47001AFE0E400745D07986C8B9B367EC9E08B1C36557C97A89BE099554DF248A5C7B1020F8F6AF009E86513974CA7B5E2BB57B172956C0542C09D75ADFB1F4F9A3E90B6FD4F840211C41175A28B166D3C8565B8761B42B38E8E81FE763D50AE2400AE6FCDF489340DF451EFF36AE265D335EB56240DA6FC7962DA822D6458C20D813BA657F806D81FA5A871C79A888B1C11F8866C27E96104130FA68C24C56F650C20174454115CC3E896429A47032FE77042B02580258A3DD837CC5CDFF7A82C5F5B4DC751BF5BF455C8A8D3403A96B680F0E73FE3A36F5612E6A26407E73F873E890E01451C3BFAB3B5CE147083CE53CF659A8D522B432B4EE4009ACCF60132D3EEC6B03A598581EEF5D9086E601DCA67E9237BE39DEA8BCA8B4424508592F9397ED0A78955E242DC7BCB5DAF4DE3CCC920A34CDD3060CEC6701C412AC92683D9661DD7AB9D9A4CF5EE088B50C3A72311FAEBD33475CD17340F3899EF8D863FF9E566A462BB0EB415D0C8B2003CD6EBC50626403012FF997CA69D4AC7BEEFE591E19F00EEE46A2A026101939B82F59A07DEEFDB032D");

        LMSPublicKeyParameters pup = LMSPublicKeyParameters.getInstance(lmsPub);
        validateSig(pup, sig, msg);
    }

    public void test_should_verify_shake_n24_w4()
        throws Exception
    {
        byte[] lmsPub = Hex.decode(
            "000000150000000F054479157C09EB7E34A7916BF4C034E24F02017B1465BE851833CB98DB4D7F8BDAADAE44FF2071BB");
        byte[] msg = Hex.decode("34A6368F588463E30473D6AEA5F2A00DAF793569ED56264209B3FDEAFDD9A8A4DCB0B82EAC503F2A939ABDCE273F3D246DF3E62791E4DCECD4E3E098AFF67DC141FDEEE3160E0096A1C74DCA43FA25E94BADE07A9BEAA2CA93CF3CADE7E0F1E16500C84D2989D14E6E821234AF70BC1090C779A1D8E2C20A4A176CE85C6E18B3");
        byte[] sig = Hex.decode("000001140000000F610AF02360FC98234DEA82F7ABFBE4D7172D1472B5AA50EE293C8137FD43508400233BD5F3CE2656C12FDFC2235D7BF081AB8D6444DD41B9FA393362C0A7DD8737880AECB9503C95AD5A02FC1E10BCEC808CA381972A282245BEC9FD146947E0E6E55F417A2851D48A1EA235D2268E84E87BB254477528C70F16AF8F9060D483777A586080E072B6333463D033F3636DCF738A8EBC25D39A0922A53346E9C16A66F4F3086BAA8EEFDE0236BAE1C2AD34175FF7902A0623BC7E70C7399D28134CA7845BCF2503B729ED7DA7DDEE5C67183883BB3BD819777CBB6CECEA92412C1660310ED4860F242F380B86202764C0658293BC3A8582F18F3D1AD17328EE3EDF91E2483A6F4C4B2F80B19C949DAFC1EABBF989185E5F84D9B0C20F00BB4299CB600A5E7A113A0B7C51C413ADCC91237625FE2B101C563AFD92CFAA2CB46635871FD1F53EECB75F1B34C016F1C5B3681A3E78BB99006AA207B694FEA2EF248AFC76A8DD493BF75A5F2B04D791014429DA4B45AD29943FD1A63F4DB14DA8C66651EA066177B425D01F8A7085E1CCC7A8F03690292C1217A94EB10329222BFFE29DECA42C57353CB2EF5870F2280E30C4FA336D5EFEBDDE938A81EC79A35A55814E4FCDCDC281FDB38319ADCB579F3983050556AC8B18CE1F23F7563D7393CF5A19D993955AE9D481D24855CEB03B7083C087DEBE441CB3D779702BDB6F123DAC4D3520CF787FACC9C1FB9EA9F4A16173822FF65DF93F657B3D16113CBB6A9AF37E4FB6FD3161FB8F20BA6B57FBE787AE8F8DE22B1A14FD5BA3DCADD8F3B73479086EE09814503D60C95709886B066C6A93DBA5C42F507CDD4DCA930A1806000D8F3F5B13C70F807EB4CA6C47FAB4014FE69D7CD6EFC1176E075B4B5F849EA48EF124E0AFBEB97FE6A00B0ECBD91D118ACF34F963E716362B6DBED5175BBEDF5BB8ACCBA80C2B1D3B2906D49CF27380406062947D5869669A524FD1AFBA970541921D6A7E7B849905699ED414CFEED47414BE208895E352AF7A8D6ECC3C0903F5F9748B0B2A6A7E333789F063DD522E7473C518CD0E4AF6F7286332A9E4EC3A33E01B3809E7B3C64525F8FB65E22FDE422FD9BF3D491CA2FCC43A8558C1AD0DE7092AE4CF5F87F5B7E871C32C2F0E70E07BCBDC3062F50630F1EDEDE66337404D3A5968139276A6034A2326F27BB22310A109A3E3DD40E20F34FD2E6716304D946441BE5227867D316D687955B975D4E19476C70103865AB935E8CB347EDCE783E9DDE38C84E277E9FCAF0B0F6B37F6E2CE17D36EB2DEBD43521A5AAA2475FF851C02617B4F9EE62687497BD62CFDC553A89DFAF553C70D20B4EBA42600D343649ECD45D1F6EF2E2F42592A9D7B90ABBCFD64A1E742F1C3C000D13ED0ED5B66AF879342CC24A44E2B84E400D0298E9923306F6D4832DF847E37F79E58457B3BA5FF4E46B41419E8F7D884311EDDA47B6575EF3571513FA24D9FAC2596707234D67127C60145F18E669B2F1BF06BD27572F56B539EA61A6CA98DB4347F3E89D482C17A963B6E8148870F18B8C9DA51216925C86A0C9FBDE75F13663C236A041463B40FD187FDCA53E6823EA55A4BBE9062AA45535F5EABAD2BC23777882E0F0C71E4E0881598D86B0F588DB9C90550B587D5B33A8D9B33980B03247E722843EB54C94E5E18A22B3326FBA8FE917C3048EBADD2CC415B49EC754504A689B96C86E6AB15A7A315A6041EA71960992DEE40E36A23D28AC8682D3C7E977D3EE295D8E92900000015675208ED60F2C8D6FC359396B44719BE9615452BCB68F35A7FBB1FF9335A421AADE038D188A1941D16FCF525958E678BCE6D17682CBAD986AB6AE78CD1ED56D1530DAB56EF8AE0FCEE2CB7882F55D1233046A38E21F7EB8C4F8E9C60F2DC692E562C113E2A5058AF5F319CFB5C0F9F344CB3219313A70CEE7C2D82AF77B0418AC61411A87A20B01EB39931457CB2946C551EF17E0021669A3658F71B37E1D7B7647EC6E08444E9B7AEE8789D79276CE53AE47734002F1E1E2D426C95E454E1B3F4FE2B2E3F12EB1CE541D4021E294F3C31C79A2A2D8E8652A371D3302D8EC4C987557836C9809210D167CFE47EDA0AAD");

        LMSPublicKeyParameters pup = LMSPublicKeyParameters.getInstance(lmsPub);
        validateSig(pup, sig, msg);
    }

    public void test_should_verify_shake_n24_w8()
        throws Exception
    {
        byte[] lmsPub = Hex.decode(
            "00000016000000104A90A81A143279659797B572866CAD245B3E55268DDF686AAE7BB9A5E77304A0C8220ECB42BD0088");
        byte[] msg = Hex.decode("0B2A3604599F2675E41098DF4EF0A570270FD86C3531E33F6C7AF3820F8BE2C1D0F4138657244ECA0AB02CF32CCEA7BD0EEC561EC9DFAA1FB08D29A86930261103C4AEF5ADB35D7D2DA24CDF5093CC95225DB3369CE6867EEAC139B4A27C6C56907D86F964CA1BC123F2044F5E94E0EA42CB24D687B68E8ABD13C0C974807032");
        byte[] sig = Hex.decode("00002F9C0000001063557BCA0E9BEF9B863138BF1701A277520C6E7E020AC0ECC0877DA741B5F21B93A98EBA55DDA341B24CE7AA336204AE0144BA4716E3304B66BEA54FB3D4177078727A5420BDA5F3E2D0F9C643CDA3B38FCF8DD3E02D169C0A8B3797BD013B6C28F26A8C2993F7712B0DA09929FF80A2CA21A6E4949558ECE114826DF6F3D8C620A1323C2CC8DCF79F917A2FF891B8B375465A77D67ED9486B4FA4F27F022E66CE076F8C908FB2BDD822B1F890E68AE57DD28CBC8943F67B74D1A3D074CB41F32658C563AF59AF583B488DBB34F52622E2359AB0805E1F4E2769C2AC4DDC3595018EE4C27799BBF3C30987263F5CAF5566E7581CCE73B1652D6BE4F8E1F6A55E00FC4F263132A025507F342B914152F9A5DC05E0EB980637C19A250B8CDBC7B68266695FC803DE027121C635438C1408CEBCD9FAD46586EEF23FEA11A724B5F515600BAF951EC8617DDB3E5FAF5D13314266F4C0F3429327E46A580213134954C4971E53B45B322CC7FF003D1C7716DBB5CE34BA8778DB8E09F399A7A99FAF402EE97F6C007FB1647DB87B0D5AE05165BA192D32AA33E3246C85D02ED388333F02BB96217C2DCC45F01791907A78FF52DF69337F3AB4D0F2515752CF75960BBBBC09020651738495AE0C5A159040E07293FDB98B8665E82166D15F5960D3A58988E9466DE59ACF4D724D254BE72820FE9A8E634B351D4B8C07E911D23FC8B0E87684BFE54C50444665FBC0FA6430D61A8BB24E2AC08BB8A7BB39866C61D5180D6F0D1DB0411A923F5050FE3E2CF2CD0692A9593EBB2D0C71221AFF04AA489218A0A5451273B2D1EB136B1758B77CC113186A2319313C06489ABE3CE22B932D2010716A06F1DC76F0BF519C16248D21544447E1FB7A002EFB39F8CC38968E1907E8DEBE076656762A0000001648AB38A35FF650BBEE245BE96EB43AC44A4C8B03D1F33CA59025C728C5703088A157BF9CDFBDDDA49E46F8A2606217C8C3AD12E68BAF369E40E24C05297383583A88DDE17F34D7347C46C6CB400239A0DE9DA2197A178C6551D563FB6A12BBE4F6524CB80B3DCFA75052DD0969C453132F7BB1636CE1B221434309D860ADBAFA86620A9778E03DE506E0C56F1D4E024B66643F2E4AE2065619575483F31ECA4DD7FA2D81180DBB9DCFE60CE660051751A4958F1683EFC5622DCD25613463F27CBD31E67FA1A84DCAEBE12787509EF6F9FEBFA83CE35A2DF445E59F60A097BEE4BE0D58068F6DA39800045458DA799ED07EE05309DF9D62D1869662A975101D1C4004B301CBE12B98DEECF2B07F3C9D0FDDE64181D4C568DD34655EE9C514576F422992E80AC9F4BE79A068F44042487B454948B58F474037C06F6973142109D1028127765236E4EB93DB6CF02D09281C8A0C690339B25BE4ED52A0D47367BCB5A77957A932FDA1A0");

        LMSPublicKeyParameters pup = LMSPublicKeyParameters.getInstance(lmsPub);
        validateSig(pup, sig, msg);
    }

    public void test_should_verify_shake_n24_w2_2()
        throws Exception
    {
        byte[] lmsPub = Hex.decode(
            "000000140000000EF45E0A263A79A7304D94B38738FA7E8AF4D7503DCC65163326FBF7AC0C8C938B2D1324456FB956D7");
        byte[] msg = Hex.decode("2EB454D4116CECF6A6CF72BEFDDCB5B6204E5689BF8901B5926692BA04BC7EBC8EC21E2B4645C99F85C9E4D9A3A855594D019264DC1C034DE09B1ADA0B71C08BA81567533503B8B2B232A5C3D6E150AC409D2CC54727D2F616532FFEF87CD12B8CBBBBF45596F779C6D98BAF121AA010991256DC9C4D46640ABCEA2C7D7E8C3E");
        byte[] sig = Hex.decode("000000010000000E31D755A2CAB086F5FA0FEADE2EB40D95FE51D049A4EF92BFC8A1C8C35AB5F53BA4FBA7159FBD49FB92D31E9E9C46C4ABBCEC9B5FC30AE94BA57F1069B189BA8014BCC57F34C7313D40C709600C45626A92E59976156A60778625891835AD009AC535AD6330376467113C40FA2C205C39BDDF64295C6ABFDCF492BDC17894EF07E697A420EB68CF91CEA8D7E35A05E5678F4F5A6A6CB9A51D11BBCE52493B9B6522CCC360ECB1B5994E695B98145FCD952341ED0FDB2847E77B82ED72921178BE12BEA40EECB0639C483AC78958F940A674E7A9A998D44B4FC854A303C2BD22738579D1D6F3F05A1018DB195906C2A56EF46A59D793C5F3FF41BF7C6A94B33FB905C21542D19EBC3AADB87ACF1D591323FDAD0A46C6E3C89765BE90709197F9B3421E6B5CEAAA4F9B28708CAF2CFC474277EB6E7C92270CE06D7948AF4EAAE482FEF2C14ABB25CC97B9CC3232C83C86315EE61949450FBE1CCF9B73A6AAEBED983E765726563A16E119FFC746DD02FFB33E434656488F5E89E322726E10F498F3BA5E40A3B2ADB97523AFF313FBCA7C953A1BF91266E6F6C86689DD95F7130EB037FB32ECC525C9A925567B3EB0C2A8CF1C008B03C60B2F8FA3762791D424F65B576E133E833B9B551546298825470B72D50089F8C9881EA7528653F2FE38734212BD03A4B2032E79365016671459515B7A0495944479EF9D8FA34E00F20CBC6CE25707E84A4926590AD87B5DF82F5930A4F9212CD0469AD55495EBEA029E12847B67FCA1857E26CF51C2F803A6B35A06DDEAC58F8D774ACE41B9765E7F950DA906709D0EAD10660458C8409C779B4A6F17E8D2262D56C727DBC57100F21FF105A83D3867D2B18147291D79E5536BD8FC2F130E6B16E7326B96D79011C38B16A983459E0B448B4AD2A004ADC38088D005F9ADEC41796E3BF1ED724A28FFA49CE287F20C894A46DA7CEBDB8AF829D32094405ECAE9A7150CCCB4D4E11E73A99CD5894880E1B6C4553A329B5788F80020E1517E64F8C1FC48CD11A3FF1CDF2E7A409B7EAA9F9DCF17855648C325C4E5AFFD9873CC49EC6C18FE592A4A1587D9EABE7DEDA216706EC699E39C7BA838DE01408EA74F8A00C9331BBC3997F7C2229E9B3C92CFD53A20D170A20D1F7EF5178315DF64265181C109689B78BF5EAC05795EB9C45C7D5ABA5B6CCFFA042A3C7D8C4B9131DEB8F665F4C01C898AC8431BB5E3B5A0872FC0929E21F66A1A92147CBC4D1975C19EB527CEE7AD046C111BFEA353AD3D8F8F5185C1E10126AE8B0FA77E10C94070EB4AF81990BCBBBFAB3C1B5036C2B5302E87B1C92A734FBBC5E79DF9AF356A0405789B166F256A5D0D0058FC32F3367EF48A29F1717FBF808D0CE1EF93E5000A4FFE711342834C03508F86DC31F55328D684B918684860E292FD15C718747A4791F11270D81EB71D0F69FE3B18A3222151125D3705FA6438510712DB2C40F776B2D81DEEF8104DBFE15C2D4B5293D6C99C734BA99B0EBFB2759B815D84F986C898051939B78E66A1E731A7F123E181F7A272FB1B8851C9B3720C3D863894A1C0AD23A0F26F72C842DCA2502C1A9987C73C9C8A1DA8B5499F0DD24E5251581718673088B65BABAAA9A235D5A49BA67A575FD632B48F48AD7E723440C5BE15BDC94897C0D1A4C1100BB6F2DBB579BA38D8FBADCAEF73A52ACEEA062A4961EF60BB73235CCD5FDD0FE99BB3E74F8473B4061FDE91CDB7E590FBEA7CDF50AA6D22986D7DE635CDC0CFFCC2F13A8222B4A6FAECED2602984CE9BB0274B059A4E4D6CBA5F4D77053FBB498772E871DC25CCF4A94AFB87F7D04C3BDF2C61D0E4216357096813E610401B440527779915CB63186DAB8F906C21252AA0BCDC263424AEC2EE33870D6D927CDA2D7D078B4B57230882F6DB6ECB2DEB273277159B3D49CAE0C7E464CA2987AC6C9FED3B57686161899E87024E079A6AEA7EE532FC1E45E84C9CA2133EEDD86D385A8FAF6A580EF62C43A551196DD18806CFF5D561C73DD29BDC2D48426E16DAB827567641B33A62EA82826E65866DF9B645DB4263C9B521AA9D403D1EEB5398E9820998516ED119A9146669BE98DC3759C094A953AE4FC1A9E645384639E88B58113971FB2B209C0F9DD5DD4F0725F0BBCC52FB1D2D98B91B980F9FD5C57860174EAF90E08A1D2F25FB12FF82071A8890DF59569EE3CEFA6BE0F43132D811FFF44E6C49D70F58E91DE03929557151155B8DD1C6A2C831E01F83C1F26052F3BC4BBE985C71A47FB41CF1A52D961E6092E9801E0116DA5E699A13A86B982ADD22427868114A062E9A55767A205B1054A7C75E9CAFA96C0C8A6AD02EE826BD3DE79DAADBD8C0FA37133768A2075394EA10491B208231F4645C991F6E15C1C73CA7AAE2C5C8C1412DA69B575F0F53AC4647D887AECA56B375570ECB2F97F100955F56FC4F40E5E0B84124EC857B1720057ABA1CE592315D0FD659B0BB403B5D5E662C44069DCB6277189C734402F8B7169EB457B8D6F6BCEFB77943D4D23F7155A0F0D33D2395CC900D7E3AC8D9AD2A341AA108EF9E16C31273714447587C98179B8C5D0449C6041983EE5F44DA3A53C56EE4F29D8EF491BF4B1D217EFD61FAAEB3714A5567C4A1607186B97F36264AF6E97BDFD32B36821B780C314D230708EB6384CF9ADAFCDEF44716E221510CF956A238E80F44F131CB523AA97FB335694753693909B55A9B39FF7A8DCA4581D35BAF87A62F42184BBBD6854CB9723F5ADBFE7A6229BE516F1727A8D95ABAC64796B857A39391AE648DC45F7F3F4C39449F7D70209489A1AAC18AAD3BF618DC2A0B6981619D7B36B2787E260602CE5F326C82C0CF6F9902A0315D501503D79A525348C18DB0BF94345E2C25CF2B5DCE32B9951D5A5D700637A9DF892E8E80B9B80FDD6E137A56AE3511CDF1D0BB3B1880BB58E40F015856D01937347E5CAAA3DADD6C579FE9CDC44222350C00BB946F6E5FDFF82C16C1BB23B2657263A00D4AE864D349A671D571A39AA80F1CF0A6979B944A1667E2AE217615BDBED3035BBA0607E096EF52ABCD3783B5C4DD11FF8E6AE5ACD465870253A5A847A37005837E0090E7E7497D7DB470FFD5728988E615610826B35D0800110ED76EB7AD10E0CC4E810929F3EC6BED6C2B5553202B4A34E0B2D7396FD5949A0A1EDA72DC7F22D5169615A8B467339ED521BEF34FF129E4E2A7DA421A0470E8787278F75579E8AFFC5AC4A089EDBA4C8DD72D4C4B1C1AFE86B7637663B81E63C1D57BE2760645A0CF40E796ED24CABE60BBAB2B66B25B62E24F0386B0A9FFBA481480D9762A4954CD89FCE01DEDE0FA3C70EF45798995446CE41044D59BFBCFF753A298161A5B912E2399C3AA237F1231247D2E17388406A0669D8FF31A719A18F6314750C95E9A66874DDC9FE9075815FE3EC4DDED0C636C090E024173A4DA4BF4301716434FB829AA971EB36DEC0A55500000014E4CDB5EC4182BD3C77EA1AF9A071D2FDBEAB9146FC4FA25CDDF308297C97F2094CCA4C4A2721BAF19B32906412BD062EB870C846C35BE01623704CC3EE555C1F7A68188D5059B1A44448103DC28661F0EAC5EF5E396C036DCDDBFB1A626ED6D6AB294B738CCE71D2C8547081D319854734D871B0EAD97E81");

        LMSPublicKeyParameters pup = LMSPublicKeyParameters.getInstance(lmsPub);

        validateSig(pup, sig, msg);
    }

    public void test_should_verify_shake_n32_w8()
        throws Exception
    {
        byte[] lmsPub = Hex.decode(
            "000000130000000C972FE777D40FE1EFD97603A62733CD1CD2D6F13C54A085F23017BBD46965C0853ABC363FABCED9119A26337A306A7B88");
        byte[] msg = Hex.decode("901F4B2AD9C744E3818519BD93C0578AC9AA6FE2B3BC3FE35EA569847C1FE797D240D846C2BFAD1FD72A784F46F393B1C1035170AEA0A569650DE986E71B0EF9D560B02772198D1B1A1E825926A5F1482C509F8A18BDF782674A5F4FDBC83D59839EF4373BBF01618D6A2DA5220DB4C55CC54F25759297C997ECE7737A1B8648");
        byte[] sig = Hex.decode("01BEA7690000000C85018B7FBF611F91DBFACC1B753B62F70652C4D50E2304209B56B2796B1F640845C5DC51829CB63C945637C786C63C5C6FF2246FA8C4F3ACABAF9CFC988486C99ABE9603E434D84EDE0A792A910870C32E0AA3C8A75E354F253F15A2D614DF441082663A96B7BDE3A3F1DFE06A98AC4AB4F104929A7E2E4EE8092B9209B0D9D0EF8A3CE9108692737B4116176C53264D4C69FBFD6669033B596065FE540BF0CF02E7F814EF821FAA5D06CF3C5C258A95A74939CEC696AB12ACBE7D2C1828249EB1AB2866B95BA1BB54BADA4E0BDC4C2F85B922B6E78793BE654F12F6C47DCB2A6505601BEE6EAD8A54CA4EAE6F778433C19FF61A6D9277DE3AE206F8C56D86839360AB4E07C1FA39D04303306967E41480C817CF1A0A9E1E731EB725138A7C6DD2D19D03AEF13032846AD0B55BCD0949B2CF48B8144F0DB17848BB957DDFB1FACD6234435D48012720F78BA6AC44531D5F98694D7C590FC69BCD332246DA9D522B423E5D2956C8A742F9E00327806B4D443EE4DF953BFDF5213FC791240326AB1D842FABCEA8896669B602AAFCCE63CC9D1AA12DE6E5E40F268F2B3AA53E10D892E3440AB8FC55D5ED743CA6E08B8615832AD3E8E30A68445DAF88F7262A6D308069627293376A30911BBB3674D099DE2DA8B700E66112EE98FA00A3C883B1FF614A685B108FE310EBF5D4FCDB457717E0287D6A3DBD71CD2B3D8B24865831291D7A4139FC36549A32EB9495A11CE6C39363528922923C5F11FCE3DC62AE05F8BA557896B28E7A280B84C7F5FBB0F6C9EB101EF95016662B8BA1856C40BA0FB074BB9136D497D90C280DFC3D4D3DF702EE22C1DED8656FE1068CB312DBA589F8529B192C3AE46BD63CCA9DBA00A9001198298E33064A187EDDBB3844469424868BC36CC54B67A427AE716616FC5EA856B6FCC08D3DCD293EC12927CC4C8E6B5A3043A03CA7DFAAADEEABDA6E5CF3D70B3F82E0132A84561FE182AAC77D180D6F787BD99BA1E1C4C4FD8CE7513A4E2446D48994BD7D58C79923B282BE71E4591812AB6D1C55A09BBF995909FAB9932668EFB3C30F123D3AA463B473037A36770325A25F401B32E6A1195D559B73EE53EA4C59BB402C21EC3CBD91B225CD059A1A9D32BBC720FD7549F0E2369F4093121A0B079D3BE5E4248EA97677FF16AFDC6193F898ADD87CD603965FDFF5887DBE29DC8E4F7CC6A7D90C9CB090AFDFCDE260CBFBE773FAAD9B59A5E8338FB918498BB333DA1877A7D1343B5903353F7AC8B79980FB062BE0D8F4DE892C647A47B1FCC058C3FA1539928854A86B7B48CA66A61B8AB79F3F4D8925D9E7472A10D3500509904A9D014ACE9B987AF34E4A893F7A87E1E52E90A0A20CD5D9D07522A4E1E6FA5D2A5A7E333D8084068A26E3758C132C111DFBA3061AA3CDBB4D0D563A3073815A1FF99FFCE701CA90747D8060C91937A3E2A0AE7781385179723EE95302C0C77C5BA2433C5B13D90B27100BAEC47C3C22C4942FF4C94543D86FB50CD6B3C551944AACB833AA76F27F6A120CB7531D6D04568CB50CB92F5EC35E8B9080E171367FD49F07B728AB210A2D1B845B92E7000000136B31C160A7BEFC143EE9A4DB1234C3BF42E11D0BE58BE77A9DBA08E9863C4737A363A15DF0D3D699365A6BAFEFDFA12DF37EC7FFE1AD91F0F0E2849F2E2207E804E244A81211B1FF8242DA525F45AAC685C0CEA936984D848376834065250025AEA126EA4C1138FD4C7AFC2C7698108A767A953EF7CDE4998FFF65B4FD4D21251F2E91411D121B6E025B6BDF6A4819AF9E094C511CD558CF65CB818A2B8EAD0936BEFDF0775C1F0A3BB67C81170C0B35F0818C747E01BF97C88FD70A93AEDE476B07BD76D4211A6650FA7485B0A985010C14A9A05776DCA4F9E8442AD1D99C57A4760342B925A0510D4132B504AB7AEB9A8FC3F43BD3CBD0EC08AAB1543C2DEAEA41FBEBAA3B18E59D5300822C2AD4ACB651FD16ADC158B9D07B3A63A6045AC0C3A9BDF37B3DF5A6186DC7EA543FFE995B6FC1C0BDEC121326A10AB866B15E9E59F8EEC40E13AEFA8B455C6093C2D0FB919BE4E3CC70A484A26DE71F11264D3E1BFD153C744EEAFFF8AFE6B08C9FF11363CCFDDA59A690A9CAB0743505A1AA99397AE4410EEA5718F003C846332F1976067224574C716A07B896668902E9701D431BF91B3E3A8CDE1E1E6680538E2BB6845D2405E7319D1731D48A40BA818BD42B1D00BA0AC6914D4E80DE31766C32C03DA53DBD20F8E773F84A79829919CA1B7FCB7CDDAD1F1710B23D19897F30E1752BF9A805A657D0CF762FE3174D450C8090A4442CAE229919C80E39550E32FF9741FD02CFF3C012E77722125D3252E144F5F6AE985324254A1582FF06F5EE565815CD0C9B820593B481C8CE3BB1CA01E51E35E8664FAF0A13ABA483B8E478DE4DD04F3CFB8A180CDC04BD2367037038CB027E146485EBE2E425AD9DC60AF5DFC1746E60265546C0B1B0513B5D047C3320A69619548D1F5143592034260B0A1777DA81C080637F4FE2DDFB94CDBFD1C09344FF72A661474721B0EEC6B52E812A8F81613EC4088F28B95F3B0D94F419AE0627121F05337872642EECE6529AE7DB49AB9A38A62AC80DD2241FA61F1A80536D75F519CA0F0145E77B9C682C47EA9D88B5CA609C1E915C37B667099FC61A15E7109DFBF24BF067271B2025C6473AB268E385CF103B0149F41F2141F312F531E4");

        LMSPublicKeyParameters pup = LMSPublicKeyParameters.getInstance(lmsPub);

        validateSig(pup, sig, msg);
    }

    public void test_should_verify_shake_n32_w1()
        throws Exception
    {
        byte[] lmsPub = Hex.decode(
            "0000001100000009747BBE12A6157879FF4FD22FEBCDB557661035CE843BBFD05D1D83E97F9635762D6E274278F02129E3E6E2E012859F1E");
        byte[] msg = Hex.decode("DDABE5B8C14869E4B912CFABE87998D626B47E608D6250946CD6D5815DB5F38DC4D7F77BFF6C12D02C86CC9A9B6F33EAF76E025F90BA3CD527E425D318966A86AC6A1A1C648F4428130F1AC937777992AAEE17C73BA0F8DEF45C0B449525DF474F04121501DDD80F353EFF899830313229BAF9F8DDBA8ABF801CFA3C9E7A6713");
        byte[] sig = Hex.decode("0000311A0000000952DD96FC53E40A9F4BC7EA5BF637C097A57384F0663BE885CDEFF9CA8AF258370F09B7C85CDF4773452AF60343D02F51CAF05FA06F83D77B4031D32CC6D05E2CDA6AADA444B1C58ABFD9AF25B60124DD2FF7B051AEE9212DB3BA3B65E9960FA49E5B01BCCAEB576D28CDFCEFBA6EF152546485E2E242BCF3C12624B22AB28185E7091B6C0DFDBFD2C3D356A785975414312300D1E6291A603C5DC29C1B25EEF149B6DA75C3D20633441DD010BEE918F039A2BD56EB4A7C1A8E002D8FA9C6C4FD1090040E3399477ACDA67ADAB1A8A4D32C6D19A1C2BBE75D093994CDAEA3252F6079CC1FCC3A6DC94178B58A31235EE52E4C825B07C82C8EEB1FCE218988B889E77017C4BD6F292A6566F5CBD8F00A1156666AA55A93852C478436E7B6C8F1DCCE8414F584F2051DAAF2841D0FAE0AB1285F1163E0C1BD143373321081231B22D4AC1F94247F490A2D1C72336F267DCDB4314D3DFAAFC4C19C83C19F6976475BA2B1D6A415B63D6E02383F8E207DB024DB10729FC9C73E512BDFD7B62D07D05DE4B153535E8B66C4AC114C03819EA39EB6C93E682044B1C60ED732A1ED8661438A6568A9D8B3D7CC0E0FDCA2D960EC223FEB2FB20479C75A5CF282BA7A722FFBC297582267AE65BC1FF14929F8CA77FB068B97DC258A798D3FC69464FB808E258D39E9F027E503D89A7A9DA7346E8DF695177A8567603E37458A77344C56D6897E4900BD17769E3869DB2C68819527C43B6813B10AC024F72811E154F9A8688F00AB549597BCC15AE5B050409C72168197974FB18A77AD8BAFD9983FBD3428EED40F0641914800431548DDBABBDC0FAB12D826EF8025410A0849A1591CC823B44AEFA11DF73C8670274A31DB11EB975229CED2AA6CB18F0B5B0FF6DF2AA3D064186FD75E93871C3385899FB93B989C59D4161BFBACD249AB5ABB1311FDD9337C0A278162B1A042538970DED88B56659079AD332BAD360AD4FDAF895F399EDED428374918B6A028A03E6FA91ED86A3D1282CB85A9CF8C038D9EB094854C919468F374EE3C3156A2469643F5E1A5A53D1F168FC225116944AAADDA902DDF74EAC2583B1C7A3C584B9BA95FF37244BDF429D1EED00F6E6474704E6AF36E4FB52A43A9B8EC4D2633BE686F1B2C1E3697EA4C4316380513DDFA2F6426D0E485F70AEE39208F3C685F9DDB7DCD059944FCC83D2A55FE59933412F65B816CC1618C584EEC8024254093E20AE97820894D64CB5F78BC2A29B8F1FCDECC8EC1F612029AD465C36BE0872EA94E07A654FB11226F79BD86297195ADD70E93EF3D44B4E132BE5A4A0C6E14BA5518408A549420E8FFC6970E72E22D7953241755D556D7C61C03065E58E89183367CBA98C9080A872BA948A7386FB2647A2272D09B84ED3E84873A4A4452A824D044DDDA74BAD4A14E19BA4F95EC606B291729AF057470E4A1C1F23DFDD8F436BE595B52052A649879C557CCA7A912FCDF6CC19A75DCA05463F98D581F726C60FFD9334FEBAFD512C846C171211069F865E7107E2F144FEC970F2AC7D729A347DAE279BF2B0AB2EB1D614509F3DC409DF59F4F070F24329358B3E9DA8D55E88A9C993507FF7E6547271F6D745846C3683176B066D6B5601774793C1998B5364A7AED6DEE1D10A6B640E09C93470B8F224859D66A922D6B43E044C02E547F511025E0379D2E7CEE8DA593F31C5DA0581B4F81271474DA124E8B890A68068BF4D166C29C04E756C98E0795B41736531B298786918B28DC972D6200FF53E2675EBBCE85C6B2196BAE7B12E18E724DA75262149C86329A3AB9F2E9811D5A521B010A0038EBCF67D146C36A8C19B3EA75FAC90FF0253E767954460BD533A2A9FC11FF253B8AC90D1CDA3E423B8A0779FFD3C99F8E48387E2D4DF4F58F0A39B64D176D1A728D08B8ACDE7FB95D8E5DFAF3C75BA4592C9397CF4F3DB4BC0C89B762CDE36E8F2E3B2BDE9C61625847949C93748CDC74D9D0EECBF0CE74820025ED6E5BEA0F1AD859A1AEB8A46772368B73DABE5D85280D7451788CEF8A8B2245AF36BFC07866BDDF43300443BDCCB81BB295082764F928B4B9F616BDE74EF47122C21285BE6B0FB7B118E66A8367677F981284B493506B258E230150EA6A4252AEF37BE771F9A3678EB56AA7DE787A2CBC7FFA3B221ED1AA3165CABCF39ADBD91BC199A226F02819DB44ECA17D2EC6F74BBD08DE84E27BB0DA0CE5FB838B955B16B9EF4FB9224F558FED474368DE479D1209AA029A8D5296571C863B6C6D1D0ED91F4C4F96A7C6FBD8E4BF00AAC214D7266655FE0092BACDFB8B755D44C74DA32E04B4ED3DA8466A4F28679BF0AC6F520F45836C4D4CD9922F170E98C999049816C6172F98BBB8505F663D6708D221783F02257ADC2EBFBDC4EB8F6E9333991BF6145AB4F4AAD1F3A276C975F183FB4C0A718F01C00197E4EDBD2EEBB9846DAAFCA14234917775CAE6401B8429E51004CEBF0F82E160DBA8C71065DE77AE34ADA1FABACC2882A9B6B07AFBB233E27620508F89C39304878F9386754801364E34BAEE0C84F61E403145898B46D8CCB46A83739381CE192C2BE23F56671AFAFEEA57B41AC213FCCC17768A5B2E2E670A16645F2E75B49140E49A1FA453BF7366A88F7A54ACBC6E8B700787327F631097DB7897B2D01E30D1764043B5ECC1B9782DFCCCF27AD9ABC6A1A7C34A6F101C2FAD29751F55676D9B0779BF96490CB89ADAF6C1DFD09E25C545B8867449C0D77B13DE71C83EAA64C3B62D03100F88344C6DE26269911052FF9AC458E2BCB14CC0D5791CA7136EF7FC5F49A321CBD71D414AD05E2F74F8C6A31B84148F793522265BBBBC818E2866929111B57918750CB09241B57438857472E3ECDD8FB00AEA0BCDE629B08AA2468D01D7A41ADF4257CED61E0D883D5E647B2261A9842BEE976EC14D8C9A5C94549287264A87C5BBE62B4AB1DEDB2056C662515FA59F95F1F73899A4D2BB25D6E05D85A299AB2859E04B4843F2BDE850025578429D4D3CCE37239AFD0346DC808FC14C0E82D14693F83D7CE6C1637B79652820A26A0E06B681166778C8FDE79F752F6C49897C8A5F35C3204E5F413843111D1FC56494B78C95E60A8B18E3353DD6BB0BBE3FEEB4A8A2365F40D24045C02B7579343F8AD58F96FAE17C6E4F0258923A94177E439B6AE1A1AD6A4FA7B3845CF5379345312A9421FC54EB14E94DE4E03F1CEEAFEEB91D276C04C35B09F267899D063D4A92C52A8E7F4A50CD3013937316DB538AA9D1FFBDCF10734563B44E0FEE8A763E1A8BDE960B2DE2FF2A872B87523C416058B6986E905710493DE4DD4AA382E36CCC3C7649E9498F410975A89F92FE543D8C7B4DEB6F91C76EA825D003DDCB9AD7CC5E4FA798271574A0AD8D0B8AC94819AC62D0DF98A80EE926270CB84305DAC94E8BA106BFAF9CF7C38E8C876842D9F8993C31A87B664DE7096608B9B31989C57743FFFEAC484F74BE49C7813D4D6175CA01B416D099A70EC05D1FE4EFDE10FC5ED3DE79ED22885C248A06C7B67DC6EC01AB7BF550000F2CD52AEE34D824BFE9A96B12379363F9B557E28495EA979012A8B93B08DBA296BEAF8FC69523B52D2CE640B867D1E9C01B8E3E99D3325EA6AFB5F255436ABCA27DFC0AE7B25FA2ACD5977523682EDBDB98A80536D4C222CBE2EE1CE48A2B49E7BDFB0E7E9C2FBFD2EE789A3C0CD8EDB5A27CB8C1E6E569AC70C062A4F4718A93FFC9E1F7A60CFA209C48D304F5B21B74B36CB8E4011E4EA813305A0908DE1F5B6E5970AE81C055DC75E43564A0EB0A9C0791311CD67DF4DA1C14F7F322E45CA1FC5A3BC6F92260349EA1F2D9DC35BCC1F3444DBFC4BBE54EC7ACA6E7C82661FF60BC47131CC368B06B96C87A132CD9F2C56ADDDA673D41238C114EFF765B2AAB915EE26F4240A76004C14248119C0097282245AB410ED3180A6BE3EC851B77150497AD8E478FE8BAF8C3218DCEFBEA141784F93B361A7039CB1AFA305537E41D7232181D5D3D83A357C0C9987E6134E19C3C155791A35969881C77218BF721B39CB98601ADD773DA256A32BAF29CF6E30CC11129FF7848F19EA43ABDCBCAEBD0441460E7EA0BBF6D1DEF00935A0B305749137DA8E7774CA30A54997832693589E6ACCF461F1CEDD5C3648738F87F12B70D79A90FD2BD8125ADD14D58B56BBB06498B4F77FCEA60CCD53A113873010920ED8459CC91F19304E50693EE63F114B23E6057B67AA87F11C326CD2DEF9B77213B69A7B5A32F5A3D5325DA18E66250EA70A5D0B345561FF8C13A3989D56AC676DCDD950EE9E6A2050C9E78B95DCE80D3D4EF383F3DFD3CF01A876C6EAE02012B43990E21BBC03ADDDC64D9D665AC8C9B3407D00C6BF6A0AC558C261D18F715B53EE02719A2C458CEF92D7A8F81E090365A9D593427BFFE4259E6BED46E7A3C45840865C300A23D3BBC787975852A79D248299888587AEBFAE09D8FC873D9708C7C37A577C5B45FE46D2A37D3E2AB6155BF23E7079F39D4B94A8644C8157505BFF98A9C6045ED689FB0A36205E8F1C49DAE5CC7E403299EC0D8921D12EAEA703A7FBCC4A990775C08B674394B0073DDD0C1347FFBC8E2FA9C0F9E321E6E78CE5BF4BF513A4972AC87D691389D08621DB73FE7BE858674840B0CEF7E541C611729EB9F91C012803B9CFFBE96E9F198D7090F5CBE3796AE3414F31D899F3A18800E8DBDCBDB1C4F06713CE80F142515B9DA59B42180015DF7DBB17AE1FAD0E97784F604A46D49459A3050AC4659C6142FD226CCFC0B96733FD31958EF70DAE54815E5D7E694BE995483BE57F37093834A963434142978D6A87A50C1384F4C5B39D7FF1A6B7B13A41CC88F47FD1A12E66163FA7411C6A18F3BF64D6D567CF0AA4608CCFAFDFC6252D899B78908BBFDC6F6F37B0FBBAB8D0FC8A0D04BD23BA3AFAB03789963743958A5CBEA0A82DD7148ED9F99B08640ADE7C00E243B7B367A818A6252CF9FE5A7C4D7CAC2BE34712F72EEE09069CBE283599A98FC314C7C66803280AB8DF1D06D20A6181285BF705FE5E64F10B1A747A810BEB16D1143A0BAD75509DF0FC84C6463B8E04B23436DDC747096047D1430C5276FEF15489D4ED30BB46E220A73142B3F479A403A356D87966022C30D2D274AB6FA9D3613663EDD00B0297F3EEBE2BF9AA05D37F53107BF9780F3A52BEA488D87E3621CBD8A2184E4F158AF83EC9354F502D46424093A1F043E6464320DB1A2801EF3EBC77D8B209D2E6C003FB4184B6D07F6986A201447024F844DBB1A1B0088F0944FCD9F917C6C3898B0585ABCA5318B4FAC2D567EE22E6EF576D05F837AF6FCAD2ED5D9EE8828501A1EF28B66F1C5EBB93A74827E25D1DE81CE764D269FBA0C4D4142960090671BB08E2A4CF6FA7902F54DEEA604555049B820B40DDDE914D38DA6C02C788A0C32C83D0060A84B77E5772B2F34418B5D45C55624E76AAC4A72A22EBCCB1D70BFBC180F6E69BE4E4B235EB476194012A0ACCB368D8933D43AE072D7D3B6C5C69722FDEF93D1579B63B5E97BB1EE8E532B6B12265B76AC97B095B26F197281199B75EE4A42D13B2E4326D6A133D0E2D31A213C2A227AFF7EF1A125F7B109766E08AEDDCD95CE76C4F9581B908D7AD61C13EB231F1E4373823FF8804A87472EE3255C513E48BFDCFD84643CA35427A01C50BCCE3DBF92D1B386641FC53AA3088ADB972D9A8284769B3AF6DF45157C4FAC869C3C2F9FB41539CE08A23B3FDD5C638329A9FF3CCFBF97CF31F3752F1DA4F8AE6F68777338ABA4DD74F6D0E2B41CC3F7196D7B42AB2B576D400363EC73F92F491D7F5341BB0ADAE4F28003C1FC889D2CDCA1E5B737DC701FFEFFDCF9D758411D610DBC994BD29F271140BB2F10A70CE373EE2E2C507F3F6A3B7AF9FE7B9A9788E3FF00D3B61BED24C5CCBC05FC7E168D418076F535162ADAFB071D4A03FA390108C3195163853620BBE389ABCF478DC9D3BF016F8DA6FDC8A42A41C68EBA40909FBE4B299F2CA3BB92E5A3BF8F6A333E90754F6B1B986053E82CB84635D02A49BC7F906D607CCBAAB8C00B7D00DDC5AB798CC5B2AC548789C55F5E8A11E36D82BBEA46D89703582263B0E51D7BE93C395C74680C7F91937050FB36F91EB0ED6BC69D1766A6FF6B4F63D3ABE81757F4662657B0C6FD5D6055656E9BC5860A1BCE1EA8516B92A1C91A30F17A0098399912113913DB3E0D8DB210B4A849383BAC10908BB34A8C4CFC389EC9B554373CACCC0BDBF6EADBB98F8E234B56DBB915CB05F7BFE12CAA308037B14421FC78146BB7D0A431F1C48D6464D693969CAB900E556DB22600058A3C7D892488389E95F6EAF47A2149271ADB0B2F899BFDF7D8AD90D255BC16ABA7A89981784C832ADF17846E80BE03D91AD04E435C22AE837DB91B138A17D3A2848F43DB72329E2426C6AEF8464B70D076CF33E1F2491BCAC5A73130A92D470A27EADFC3D27B9BA7BE3C41BA19A22C221FC5406639CC17CF4774B72EC3966981645C0465B8BB642213748D9D8577312570B1B6E6330F0008EF7B9EF14181B021A7E4D6F2F7C3C851B575202E95A1EB629BB445C862BD3D8B685AAC120B68702B185C40EF4C6D476808457BDFB2D9240FC68EE394A5C7BDDF2D6F94A712CD23B1244D264C951B1F255DBCDB73824A090848DF23F6BF81C09D08B22C39D2F5E5D0DDF25DE1AEF8BF582AF8B63C336A94951222F9BCBA5F6378A5DCF3A0EDF099182F139B78D9B4FF36FADA90A6B81ECCB1433145C8B2EE134C40D8A62EE5D93581ED4357EB438911984222710C73E00E0EDFCC4496C3C5AD9B8108C739919B47B0DA2190729061BD231968755F9FA20E9592328A1D38D6E163F90674EE5DDDE399047DFD8D9DEDE9C8B4C400F679715F94E280A82E656120A7C07397BD45699B592B47BB46E5900DBF960E9CD2FDBF7E42EC03132ADBC4ABE84B5AB5B99C25A970680DFCE0EB5D80E9CFD322B3ACEB482E9E4E41E94D115E32FA59DB80DE5DE5F7A0961EBE503E910D04C8348CA0643B0CBCDF3EDE408521ECC0E3C51D2F7A585B7D0C932219CE10DB7D379B7ADA72E140FE2FB874A2B8A9F3AE9DCDA72997EA250D89AE01A1D068C3CF45999C41A64B9BCA2580E2E908861AFE20B8E2EAEEB681B999198947AA1A8C40868B768ACB27667309C2D8EB23FEA15BB913F578E7E68DD46902BBED322D6522C636A34BAEF8D1A90F276F2E9731B8FE52EC138A77B1419AD55E76EB7582772C0F52E92D626FF35C2C1DCFDF2D06097A1D11AFB229D6243FEBDDFDD8661A8C0099E57FED15872B03C64DADE274BFF9BB0FFFBCFFE39DCBCF4907765424904FDB45AE1685C661DDE3105D9B654601945D1B203593A244C96104E23FA67A348C55A47D0D29BD3834212692AAB1D202C806D27F2212A5A8B0A70A9C69FB3F484BA018BE45029ED18F6147A0DB6DD6222C227A6E65055805075EFD205DE6E6C9381F4C8B27AC3ECD2E6824CB173964294AEADC29A50B82C72ABF8E20A8EAA722FD60A68DA2BCB97DD3AA64942A1D36057BD66768FFE73DC004A09D8410C94CBE4DEFC198F8D7727B5486A87FB4B8C349AED75184EA870B878A1977612CCA52BFF2C3D1D4BB2F362118DA2F0E2069434EC1809145B878A5F8FC908A3D5C26BD9B7721FC94CF20BD9003F4226CB3A1E082C4B6D313AE3EF5864FEE44C37AF446C12BE60003EA632A581FCDD92ED6E4B71A3E0660F35C2708FFE81A1D87EA58A66CCFED6D1EEAEE92233404C55B94BF53E1B14AF54C9685B2746569BC6916E526589710881FA533DBF303055224909F547CCBB2B0CB084F07DB6BDB5CE21B3E4AB8F898C1EF41349C3EFFBBA1E06DBF90CA1F6A8C52403DC8752FDA0E394E9CA917FBF6C93B81174DD8724105D44C3DE8A6ECEDD821CD21A126311B94D20AEFF994DD606D37DC9FF109C130037CAA06EDC7E9575D22E0DC773566196FE6D939868BAF108827CDD2751EC6C79ABDAF9B13DBE8457ECFFD1DBFB8417E6051E1284244EFD8FA8674EFEBC872A6A5EE2F953CB2B4CC79871A0CC35A8128BF9297C8DE3DE2EB340001239660E4B4283B9A731F00339ADC3487DC9D6663D9FCD14A3F51874A20F06EDD43A2F51DEB1EC3FEBA2A2EAD966394179E5DFD052F368C30D6A624E127BC8D669E04A2755E6FA23FE63F89EC6CF429978FA798AEA92F11D26438A744D9295AB5C5893EEA9F4581C5F6D2F714E849D73F2CD28B97CF0E65D30FA3BE012819DFFE0ED03FD0E7585E04E6FC26D351A32D78CE6C73A7F6B8DD3749D466C64A9A6DECDB6F2CC8E08A036814369D8EB62093038CA2071542664F2FD404D3708E4986148D83A220757A561101BAC4291A7709F2FFFF3F58BDD204F52CF99BE94BF785DA56D14A2DAFF3034C8B100804AB3F770404C61EE3B94D5E1A0E777FEE2335838A16FFDA4864EFE6E7279C8843A741C72C14D22B6DBCC25E98BDFEADCCC7644FD6A0013DEDCCF2A41FA662D35AFF87B2A9A6E520A273F789EA078972833901B7AB992B5B15E5CEE61B8A3DE3FC6889212EA3D3D036F2E4E20C6B4BA48985286268A8A2ED1A3999A9DB45F204064609B01399E5B3ADC938D3D4A382A387BBF6EEAA9FFDC74E766A17E43E47EE3926C8EAD5890B90E8F999F53F5769F2FF70F3C8A925ACEEDD1628505BD5BBE4C5AB16B8495B1D1C94919300CBB37787630CB18F0014FD4B3C6EB861EEFFE30D49C63AE6E7126A3B4627AED08AE12989B60816A65E8BC2EFAD36C5ACCFC56FD00ED46DF05452A8B2904D215E82B54CEE9B3174628D48B89B78DB4DE765E45D43B01967D3088B80D73091BEEA082DB9B335B2E736B3F7D8EF13F7B2B6C478737B86F82150170588CD5CC1833191F0DD59634B8F931B9CD5196D8C3A2FF3F5D8B47EB0D811197757A2DD3E01C5414FD3557F9B65C683130C0E5D8ED861F78C3C46B7A531535BC7B0D63990F1B1E1B7545B278F355BD84AB17538BB09D6AD1AF260F87266178B01C55DD99A02D7FC090C81AD3C71FF350F21C7E8D47C24CBD270D256C3F5C8892C4F6E0B164DCBF9F7A8638F100BDAA74809FE8CB9739896DDD7A4A2319000575010BE77A56A6E38E56563CE5B7F84C227D5C8AF8DB7E52AA65B3D6ED1B8C0456B8A0B27CBF918703977F0B14C41A855A776067A99D07EC16BCE384F24FB0AC8C114A57557958C56C522804D350CA628B7216598261EE17826398440B0BABDB8A5D33686796CBB5D92C5F2A61C52EA4118E9C3114AE909937C80BAEE2A1615625ED6510A21F38A21C6937BF4E2A8146A834D00F0A0B92D9548E36E426673DB303EBB3014C8517E5FFC5E7C129DC85DB8295469A909A5E30A70FC005953C1EE798288457D1A44613803E7877BB1F9EE4BD655B3BACC7DBB262099439BD651864833A08F5029CD9BE1CFBEDE6D3E41E592E76BA026FA4CD452B35E26EE5F22E639414AAC8A5EB39D9F6328CE0A005D6B219A33A87035654C82DCFAE8ACCD7E8DF2DBE6F90BE0C3D92D7330D2B13A8F670FEAC799D4F363FAB14DB819A4F2DA5C1A625FA727ADBE95F584659294D0F5263DF841F844C801D88F8F3C8651F3BAB8C57BDA7A975A25ABD890148DE6FF5BA0A5FE2629BC075DC256A13FEBBA0C9141F1816C2A723328C647A27BC9C3C40FC6C3AD6DE0C0A128EB3FB4572D373A4D1FD6418B7941F4491C9E80E075D79CCF5C410CD258FB98046DC4D44B292EA522314254C2FF3B3E03646352B238D96B779E06625C9E0CE3025C43854B2DC5A9CBCD164D1891D48297AFFF53CC8A415745157C77B86FD7D18BF72D1B3782FE05B993695BFD185680915B1548F607430FA198523F679AC6054D2A1F5CD7C4288088A1E06FFA0DABCC625701BA121DF5E7B325275062016575BC57D41BB201731EF316D77BB005704E1206D61FBD3940AC6B88B856306DFAF482B7BFF58ACF2F48BA949401291E925813AE305578237657FD1272029C8EDB7B746DD97B063A748DD27B3D127F11DE4CA095BF65198783F38FF0178BD9DE2613D09BD82F40E6261B1C6E1D783C90918D8346B73653F8394DDAA4225C8194F727A3E5B5889363290499402C3D5A25782B9CD6F445C782767D07B9581BEE9BEF27772DA3A9D3F4EA979736FF8FBA7CFD316C9DB70E009275B94F6618A149F6CEAFF0043811002D8EBC02AC8CD27E666234BBEC4532CC1E56FE2CD60A3A5899CC2F705B7CEB8D1CF926AA6B22E8D6E6DC9591D335F59C452FF0E9DE1D3CE3E2059232C2B20CA082F882A7D580038F75E83717151F1B664F047E8C3D67782200B65B3C168D8EF63936670DABC4163E4C2EC4CABCBBA17BA551854A22469B1438665473819F5FD513AE1609234CB32738E13F2505B12B6445BE0A2702BCB0C83D3EB6B6132AB99F1E5D85883141BC7A728CADF4DCA75EE10DA77B7E76098DF23A94A14263253548C9B52636A5B450C6B768A4323A11B1BA1D9B5AFCAE2C2F16F4CD12F93A3E699216A0DA59C5A786A060B13A8D6979E1AD0E3C677B4FC7B9A95C064ABD49B774259DB60327324CA794626EB78028834173B9DDC44CC8436B96872F3360DF52694E144510F6E6DE8802A8388BE71959824F9D1E4910DD8262DA9F2DB2164603544C7360A9D34CEE8CEC1DC0CCCBA0DCD04B5AA34A025BE887657C0FAF54D5B816CE727EE6C580569B5575DAAF097BC001A0AA8576BD79B501E86F8D76478DFBE049833F13B9BC582B190929D7235F1C6F4006F98F95DCC6ADE891A975B3DCE565906949CCCA81C7C349F1A836726775E2180E61288D072C4B241677224490EA6C4EB198F47FCB8A5033945B917DB7A2DDD78030BF20A61454B7D34762E7F1CC605A1F110B7E3B71AB51368979383E63BA15019F588BCC9A6CA4CF31560B183630FB3C72307792349FF9854C50BC5496D04C83968739150CFEDE73BA1D14270B435D3279EC44DEA35A54EBBE8E510A96600E6E7C716C520E36A6BE39F4AE6E2CB3E1E308B3850BE07FCEC9D6194F736C4E76DB331FF635780F3F01CE22483ED9AA4306EC02DC5D93173E25FCAC18F22A9F7D561EDB2F991157D5B3955AC1B8BF9C9711D16EE270BD1C1063C13A97225F7183F9E79DF127D95B57FF7AAA1806BEF90A69A2098E4380FF41B9F49BEBEF163843499FD7A7E1C11448E2AF7FCFC75EE12FE7B0E52FF564B3D933A30A4CF2B6F61D429E26486A486A2216867EC27C1E09B0E7B91601D8CF8D9AEEF9C21611704A03EE133E889900B5B844B14684FAF3C1B0CA90BD29BDA01AE2ADA810ECBFFBA4E049E57FAD602F52E44CDA8DB83BB2EDE93013CA0B93F8A96F2F10E86EA2B97544A9FBD4BC552905239F68862CF0BB1DB58F2DB72494843AA6E02CCB511C8033E3E0C81CC5AAD37B6ABF50A6FFF01479F62CE75EFE8B10CFF11198C796466D5E88F82DD34AF6B7B053E57CF434D343EF797A8ADA19FD54CBEA5269C4CC98A4BA08A84F0F3FD99C9EFECC52C809DDA5C8D7EAF07E3F04F522C1E391F66095B0BECE865B687457608287271354EB93AA7696735A953874E6ACA9FDA6A0FB6CB09F2047862076FF26F585CF7A153E4B7D0B8C44F5090D6B306DC353E527EF3D640415D0D26F66597576DF563930D2D56292A79D407E180D6CAE2D09BAF5399827161BA7709F94838B2F2A54E3F609070CFBD07F125ED3FCCAFF31055E7E5D490D71F1A7933BD1DE69F7A4FB90F55D3BB5D24D65D93F139E460707FCBEFF7BC576AD569425EDA6DBB9C5447BBDA584D6E917429EA97753D77FC5617002AA5AD59199EAC87D6BCD014BABA2AA4C540F04CFF6688E55D73CFE243866EA513B708640704667F5D57F07197DFB543A846B57BE678A981231CC31307D9757BC74424A7384965C0206A6EA6D38C51708BDFE14AADF9098F5A70453687D7B34C63BA049D6C76F7D8BF27A4BC1ADE1E69FE8A3A4C0940546164C779E5CC8A87C1846172E995F63CD13000E911659553887D1A1D30970FB8BC4CB945E62F15640C4FCD17C6816E3EFBFAA6597583B6E5438AE90AF1FDEFF8006F233F15BBAB11C4A7798826B92EBF413921BDD5A6AA6A4955515488D52640942321700000011C0FA3E14FEAE4083E11A1F1CF9D2838E320F200E7BB540EBEEA4112178CF61D30C30AC84ABBCF974D68351778A9237C5046B257A6DD13912889EE7A319348592AB8BF53033D9861F701275E75F6D4D131DCC07B103544E20803A7668E9A73D8462645460DD7591F7C176EA2854A90BC6D00BE11D4929703C1A3358EAEB7A8963198DE33243AF991589AAC9697677EA08466CC44186CBAC009254051E00F117DDC6045C8D47D351D50B8CA60B75B9E1B06F30102F1941C22FA02C93E818A7BA4299A663B730FB9A66F331B394CDABFDF38294CA7B6E9A18E8BC146BEE4811C3E621C544BF9DC211663D23B883D93AD0A35FA6EB13985111F7DDE724934BD8DAFD16EC1B94136592E8ED70F0D5853059D89657630EBBC6C4A31E7BCB995B9B70D558FCFEF9E0DD455E0641180470B7C568410FD5D2377252E975F738B9E0DCE7059B6718741793FABD2601E0F4711F4FBAA3E0C24B214FD0A9F828851D427901BA5959C1E1454766995EA5D57A474A0DEA12D0D8B4837B435A503DEE193E0E295E0442DAB2AA09A4F97DB027E64777167B7BEABEB9F57A9791581935131BBEB3B877B4B8CF761CDBF46A7FA5315E86D5C6C6AADE19645229E639C8CEFDE810A8FD1B9D12C90379E42E0F406E64784D9146C175C3B630847664AB7D311348F9E1BA");

        LMSPublicKeyParameters pup = LMSPublicKeyParameters.getInstance(lmsPub);

        validateSig(pup, sig, msg);
    }

    private void validateSig(LMSPublicKeyParameters lmsPub, byte[] sig, byte[] msg)
    {
        LMSSigner lmsSigner = new LMSSigner();

        lmsSigner.init(false, lmsPub);

        assertTrue(lmsSigner.verifySignature(msg, sig));
    }
}
